【问题标题】:Expression not evaluated by SQL ServerSQL Server 未计算表达式
【发布时间】:2017-07-13 10:09:21
【问题描述】:

我正在尝试让 LINQ/SQL Server 解析一个表达式,但它似乎无法处理该表达式并完全跳过它(尽管它适用于内存数据集)。

    public static Func<TSource, bool> WhereNotNullClause<TSource>(string propertyName)
    {
        var type = typeof(TSource);
        var expression = Expression.Parameter(type, "p");
        var propertyNameReference = Expression.Property(expression, propertyName);
        var propertyValueReference = Expression.Constant(null);

        return Expression.Lambda<Func<TSource, bool>>(
            Expression.NotEqual(propertyNameReference, propertyValueReference),
            new[] { expression }).Compile();
    }

调用如下:

var whereNotNullSelector = Expressions.WhereNotNullClause<ContactItem>("property");
var contactItems = context.ContactItems.Where(whereNotNullSelector).ToList();

生成的 SQL 不包含 where 子句,因此 where 似乎是在查询解析后执行的。 在正确解决此问题之前,我还需要注意哪些事项?

【问题讨论】:

    标签: c# sql-server linq lambda entity-framework-5


    【解决方案1】:

    您的方法返回的是Func,而不是Expression。该代码必须使用Enumerable.Where 而不是Queryable.Where。这意味着它需要物化数据,从数据库中拖出整个数据集并在本地运行过滤器。只需将返回类型更改为表达式并删除.Compile

    public static Expression<Func<TSource, bool>> WhereNotNullClause<TSource>(string propertyName)
    {
        var type = typeof(TSource);
        var expression = Expression.Parameter(type, "p");
        var propertyNameReference = Expression.Property(expression, propertyName);
        var propertyValueReference = Expression.Constant(null);
    
        return Expression.Lambda<Func<TSource, bool>>(
            Expression.NotEqual(propertyNameReference, propertyValueReference),
            new[] { expression });
    }
    

    一些额外的阅读 here 关于为什么你 Expression 而不是 Func。将表达式视为数据而不是实际的委托,这意味着 Linq to SQL 可以将表达式树转换为 SQL,而 Func 本质上是一个黑盒子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多