如何“停用”实体而不是使用NHibernate删除它?
我不太确定这是否真的很琐碎,我只是把事情复杂化了,但在过去一个小时左右的大部分时间里,我一直在思考这个问题 所以我有实体。因此,NHibernate。我想做的是,每当我想删除实体时,只停用它们,而不是从数据库中实际删除它们。只是因为我们不想真的从数据存储中删除记录 我的所有实体都继承自具有BaseEntity.Active属性的BaseEntity类 我现在运行的是实体类映射文件中的以下内容: 更新SomeEntityTable集Active=0,其中Id=? 这可以很好地工作,除了我必须为每个实体(我们没有在任何子类化策略中实现BaseEntity继承)将其注入到每个HBM映射文件中,并使用表名进行定制 正如你所见,这可能有点卑微。编码将是乏味的,维护将是可怕的,并且在同一个映射文件中声明两次表名会让我感到不舒服 我之前考虑的是我是否可以实现一个事件监听器;可能是OnPreDelete或其他,并更新实体的.Active属性,如下所示:如何“停用”实体而不是使用NHibernate删除它?,nhibernate,Nhibernate,我不太确定这是否真的很琐碎,我只是把事情复杂化了,但在过去一个小时左右的大部分时间里,我一直在思考这个问题 所以我有实体。因此,NHibernate。我想做的是,每当我想删除实体时,只停用它们,而不是从数据库中实际删除它们。只是因为我们不想真的从数据存储中删除记录 我的所有实体都继承自具有BaseEntity.Active属性的BaseEntity类 我现在运行的是实体类映射文件中的以下内容: 更新SomeEntityTable集Active=0,其中Id=? 这可以很好地工作,除了我必须为每个
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。删除方法也可以进行级联。。。每个实体将指定要级联的集合,仅此而已。