【发布时间】:2011-07-02 21:15:55
【问题描述】:
我有一个带有被软删除的子对象的实体。当我在父对象上调用一个简单的 get 时,我希望它在未软删除的子对象上检索。我所有的实体都有一个基类,其中保留了 id、审计、软删除字段。
为了实现这一点,我创建了 2 个事件监听器和 1 个过滤器,一个事件监听器将在必要时级联软删除,另一个在预加载时应用过滤器。
public class NonDeletedFilter : FilterDefinition
{
public static string FilterName = "NonDeletedFilter";
public NonDeletedFilter()
{
WithName(FilterName).WithCondition("IsDeleted = 0");
}
}
public class ParentMap : IAutoMappingOverride<Parent>
{
public void Override(FluentNHibernate.Automapping.AutoMapping<Parent> mapping)
{
mapping.HasMany(x => x.Children).Fetch.Join()
.Inverse()
.Cascade.AllDeleteOrphan()
.ApplyFilter(NonDeletedFilter.FilterName);
}
}
public class PreLoadEventListener : DefaultPreLoadEventListener
{
public override void OnPreLoad(NHibernate.Event.PreLoadEvent preloadEvent)
{
preloadEvent.Session.EnableFilter(NonDeletedFilter.FilterName);
base.OnPreLoad(preloadEvent);
}
}
这就是问题所在,这是最糟糕的问题:有时它会起作用。在我的测试用例中,它完美地创建了 sql。它选择父级,为子级设置一个左外连接,并确保子级 isdeleted = false。在我的应用程序中它没有,它只是在不检查的情况下进行连接。它适用于单独的父/子关系,并应用了相同的映射覆盖。
配置基于相同的映射构建,具有相同的过滤器和事件侦听器。我能看到的唯一区别是我的测试使用了一个内存 sqlite db,其中数据库是基于映射创建的,然后执行初始化 sql 以预填充数据库。但它是根据实际数据填充的,我找不到任何差异。
此时我想我的问题是我应该看哪里?
这是我的想法。桌子不对吗?他们看起来很好。映射是否缺少某些内容?它们看起来一样。是否未应用过滤器?好吧,这是另一个。过滤器是否工作?这是为了另一个。
也许我看了太多代码,看不出问题所在。任何人都可以说明我应该在哪里集中精力吗?
【问题讨论】:
-
一般来说,除非您有真正令人信服的商业理由将软删除的数据与您的实时数据混合在一起,否则只会导致一团糟。 ayende.com/Blog/archive/2009/08/30/avoid-soft-deletes.aspx
-
我知道这只是时间问题。每当提到软删除时,总是有人必须指出应该避免它。开发人员手中很少有这样的选择。我会说软删除是一项功能,而不是审计或归档的后备解决方案,这是 ayende 提到的重要但经常被忽视的注意事项。因此,如果您了解软删除要求或要求不灵活,请不要害怕此处发布的解决方案。
-
评论不一定针对您,而是将来偶然发现这一点的人可能能够做出自己的架构决策。
标签: .net nhibernate asp.net-mvc-2 fluent-nhibernate