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 本质上是一个黑盒子。
我正在尝试让 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 本质上是一个黑盒子。