如何“停用”实体而不是使用NHibernate删除它?

如何“停用”实体而不是使用NHibernate删除它?,nhibernate,Nhibernate,我不太确定这是否真的很琐碎,我只是把事情复杂化了,但在过去一个小时左右的大部分时间里,我一直在思考这个问题 所以我有实体。因此,NHibernate。我想做的是,每当我想删除实体时,只停用它们,而不是从数据库中实际删除它们。只是因为我们不想真的从数据存储中删除记录 我的所有实体都继承自具有BaseEntity.Active属性的BaseEntity类 我现在运行的是实体类映射文件中的以下内容: 更新SomeEntityTable集Active=0,其中Id=? 这可以很好地工作,除了我必须为每个

我不太确定这是否真的很琐碎,我只是把事情复杂化了,但在过去一个小时左右的大部分时间里,我一直在思考这个问题

所以我有实体。因此,NHibernate。我想做的是,每当我想删除实体时,只停用它们,而不是从数据库中实际删除它们。只是因为我们不想真的从数据存储中删除记录

我的所有实体都继承自具有BaseEntity.Active属性的BaseEntity类

我现在运行的是实体类映射文件中的以下内容:

更新SomeEntityTable集Active=0,其中Id=? 这可以很好地工作,除了我必须为每个实体(我们没有在任何子类化策略中实现BaseEntity继承)将其注入到每个HBM映射文件中,并使用表名进行定制

正如你所见,这可能有点卑微。编码将是乏味的,维护将是可怕的,并且在同一个映射文件中声明两次表名会让我感到不舒服

我之前考虑的是我是否可以实现一个事件监听器;可能是OnPreDelete或其他,并更新实体的.Active属性,如下所示:

class BaseEventListener : IPreDeleteListener
{
    public bool OnPreDelete(PreDeleteEvent @event)
    {
        BaseEntity be = @event.Entity as BaseEntity;
        if (be != null) 
            be.Active = false;

        return false;
    }
}
这样,所有支持停用的实体都可以自动执行整个停用操作

问题是,我认为NHibernate仍然会构建一个适当的deletesql查询,该查询无论如何都会从数据存储中烧掉我的实体,而不是更新它,所以这只是浪费了automagic的努力


我该怎么做

您可以使用事件侦听器。您还必须将侦听器添加到配置中

public class SoftDeleteEventListener : DefaultDeleteEventListener
    {
        protected override void DeleteEntity(IEventSource session, object entity, EntityEntry entityEntry, bool isCascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
        {
            var softDeletable = entity as BaseEntity;
            if (softDeletable != null)
            {
                softDeletable.Active = false;
            }
            else
            {
                base.DeleteEntity(session, entity, entityEntry, isCascadeDeleteEnabled, persister, transientEntities);
            }
        }
    }

由于很明显,您从未像大多数应用程序那样实际删除持久实体,因此不需要仅仅因为存在delete方法就使用delete方法

另一种办法:

声明具有活动属性的基本实体 对于删除用例,将其设置为false。您甚至可以向基本实体添加一个Delete方法来实现这一点 此外,还可以避免加载已删除的实体 是的,这涉及到一些工作,但从长远来看,这是最好的,因为您仍然有一个可维护的、非黑客的实现


如果使用基于代码+约定的映射方法(如ConfORM或Fluent),可以减少一些负担。

设置后,我是否也必须以某种方式更新该实体。Active?类似session.SaveOrUpdatesoftDeletable@理查德:这不是必需的,nhibernate会使用脏跟踪来确定刷新会话时是否需要更新。谢谢@Paco,@DanP。我想我会这样做,只需在软删除条件块中添加对CascadeBeforeDelete和CascadeAfterDelete的显式调用。虽然这样的实现肯定更适合我的口味,但我实际上正在考虑修改实际的NH delete行为以利用映射,因此,删除也自然地级联到实体的关系中。过滤器的建议是一个真正伟大的触摸虽然,我相信我会用我的项目。谢谢+1您可以使用BaseEntity。删除方法也可以进行级联。。。每个实体将指定要级联的集合,仅此而已。