【问题标题】:LINQ to Entities does not recognize method inside an ExpressionLINQ to Entities 无法识别表达式中的方法
【发布时间】: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


    【解决方案1】:

    我需要如何以实体框架“理解”如何将其转换为 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 2014-08-09
      • 1970-01-01
      • 2012-04-03
      • 2021-11-06
      • 2012-05-03
      相关资源
      最近更新 更多