2017-02-06 53 views
0

我遇到了使用EntityFramework /“Linq to Entities”的概念性问题。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查询?我敢打赌,我在这里的东西很简单......

在此先感谢

回答

2

如何做我需要构造的方式实体框架“理解”的表述如何将其转化为一个SQL查询?

而是反思的,你应该使用Expression类的方法构建它:

var parameter = Expression.Parameter(typeof(TEntity), "o"); // o => 
var left = Expression.PropertyOrField(parameter, _efRangeEndPropName); // o.Property 
var right = Expression.Constant(null, left.Type); // null 
var condition = Expression.Equal(left, right); // o.Property == null 
var predicate = Expression.Lambda<Func<TEntity, bool>>(condition, parameter); 

你可以把上面的一个单独的方法,如果您需要在一个以上的地方。结果表达式(predicate变量)与EF兼容,如您所见:

var result = EntityCollection.SingleOrDefault(predicate); 
相关问题