SQL 服务器未评估表达式

Expression not evaluated by SQL Server

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

    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似乎是在查询解析后执行的。 在正确解决此问题之前,我还需要注意哪些事项?

您的方法是 returning Func 而不是 Expression。该代码必须使用 Enumerable.Where 而不是 Queryable.Where。这意味着它需要具体化数据,从数据库中拖出整个数据集并在本地 运行 过滤器。只需将 return 类型更改为表达式并删除 .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 });
}

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