【发布时间】:2017-02-06 14:05:08
【问题描述】:
我在使用 EntityFramework/“Linq to Entities”时遇到了一个概念问题。
假设我们有一张表,我们正在根据名为“ValidTo”(类型:DateTime?)的列进行一些过滤操作 我们可能会编写一个如下所示的查询:
EntityCollection/*IQueryable<Assignment>*/.SingleOrDefault(o => o.ValidTo == null);
这个简化的例子工作得很好。但是随着应用程序的增长,我们可能需要对不同的表使用相同的逻辑,并且我们想要重构和 将业务逻辑与特定实体的上下文分开,以确保我们不会违反黄金 DRY 原则。
这一次我们必须在运行时获取列的名称,因为类型是通用的,因此在编译时该列显然是未知的。
我在运行时使用反射来获取列名。代码最终看起来像这样:
EntityCollection/*IQueryable<TEntity>*/.SingleOrDefault(o => typeof(TEntity).GetProperty(_efRangeEndPropName /* ValidTo or whatever... */).GetValue(o) == null);
注意:上面一行会抛出异常!
An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression.
据我了解,实体框架无法将此表达式解析为 SQL 查询。我目前的解决方法是在过滤数据之前将对象加载到内存中:
var entityList = /*IQueryable<TEntity>*/EntityCollection.ToList();
entityList.SingleOrDefault(o => typeof(TEntity).GetProperty(_efRangeEndPropName).GetValue(o) == null);
此代码有效。然而——你猜对了——我还是不开心。虽然在针对小型数据集运行查询时这可能没问题,但通过这种方式无法避免大型数据集的性能问题(必须首先将整个数据集加载到内存中!)
我需要如何以实体框架“理解”如何将其转换为 SQL 查询的方式来构造表达式?我敢打赌我在这里遗漏了一些非常简单的东西......
提前致谢
【问题讨论】:
标签: c# .net sql-server entity-framework linq