【发布时间】:2014-01-24 08:57:01
【问题描述】:
我已经为这个问题浏览互联网很长一段时间了,但我得到的关于覆盖 LINQ 方法的结果要少得多。我不确定它是否可以完成,但我想知道是否有人可以确认这是否有效,或者提出替代方案。
情况如下(当然是为这个问题简化了)
我们正在使用 EF6 Code First 来构建我们的数据库。我们添加了一个自定义(抽象)基类,所有实体都从该基类派生。这个基类实现了我们用于审计的一些字段(创建日期、创建者、修改日期……),但我们还通过在基类。
就我们的应用程序所知,不得返回带有IsDeleted == true 的项目。
DataModel 如下(再次简化)
Company
---> 1 Company has many Departments
Department
---> 1 Department has many Adresses
Address
过去,我尝试创建一个通用的检索方法,通过创建对 DataContext 中的表的“覆盖”(也是一个自定义类,因为它自动处理审计字段)来消除 IsDeleted 对象。
对于您在 DataContext 中找到的每个表:
public DbSet<Company> Companies { get; set; }
我们添加了第二个表,它只返回未删除的项目。
public IQueryable<Company> _Companies
{
get { return this.Companies .Where(co => !co.IsDeleted); }
}
所以我们调用MyDataContext._Companies 而不是MyDataContext.Companies。
这按预期工作。它很好地过滤掉了已删除的项目。
但是,我们注意到随后的.Include() 语句并非如此。如果我打电话:
var companies = MyDataContext._Companies.Include(x => x.Departments);
//...
公司删除的部门也会返回。
在我们目前的情况下,大部分核心业务逻辑已经实现了,而且这些包含语句到处都是。它们主要与安全有关。我可以更改所有语句,但我宁愿首先寻找一种方法来做到这一点,而不会对现有代码产生太大影响。
这是第一个应用程序,其中查询的大小不允许我们单独调用每组实体(通过仅使用直接表而不是包含语句)。
所以我的问题是双重的:
- 我能否覆盖
.Include(Func<x,y>)方法以自动检查所选实体的IsDeleted标志? - 如果可能的话进行覆盖,如何将传递的 lambda 表达式与我要执行的附加检查结合起来?
所以通过调用
someTable.Include(x => x.MyRelatedEntity);
它实际上会执行:
/* Not sure if this is proper syntax. I hope it explains what I'm trying to accomplish. */
someTable.Include(x => x.MyRelatedEntity.Where(y => !y.IsDeleted));
谁能指出我正确的方向?非常感谢!
注意:我知道我的问题中没有太多代码。但我什至不确定我可以在什么级别上实现这一点。如果 Include 不能被覆盖,还有其他方法吗?
更新
我实施了建议的解决方案,但我遇到了所有数据库调用的问题。错误如下:
Problem in mapping fragments starting at line 245:Condition member 'Company.IsDeleted' with a condition other than 'IsNull=False' is mapped. Either remove the condition on Company.IsDeleted or remove it from the mapping.
阅读此问题后,似乎如果我使用 IsDeleted 作为条件(即建议的解决方案),我仍然不能将其用作属性。
那么问题就变成了:我如何删除一些东西?一旦被删除,就永远不应该归还。但是一个未删除的项目应该可以被删除。
有什么方法可以通过 IsDeleted 过滤返回的项目,但仍允许将其设置为 true 并保存?
【问题讨论】:
-
改变公司类怎么样?您可以尝试添加一个选择未删除部门的属性,或者您可以重命名以使其在公司内部工作: public IQueryable
_Departments { get { return this.Departments.Where(co => !co.IsDeleted); } } 然后,使用 someTable.Include(X=>X._Departments) -
你会如何改变它?此外,这是一个简化的示例,实际上有 13 个表和它们之间的 18 个关系。更改实体是可能的,但前提是它不会影响整个代码库。
-
看看模型,当映射到模型时,您应该能够过滤(我相信它称为
Ignore)行。我的建议是根本不要碰Include方法,它处于错误的级别。 -
似乎 Ignore 实际上删除了一个字段(大多数谷歌结果都是关于 NotMapped 属性)。我试图强制评估属性,而不是忽略。如果我误解了您的评论,对不起:)
标签: c# linq entity-framework linq-to-entities