动态 Linq where 子句抛出 OutOfMemoryException
Dynamic Linq where clause throws OutOfMemoryException
我是 Linq 的新手,也是表达式树的真正初学者。
我有一个通用的表达式例程,它构建了一个简单的 Linq where 子句,我在以下位置找到了它:
https://www.simple-talk.com/dotnet/net-framework/dynamic-linq-queries-with-expression-trees/
public Func<TSource,bool> SimpleFilter<TSource> (string property, object value)
{
var type = typeof(TSource);
var pe = Expression.Parameter(type, "p");
var propertyReference = Expression.Property(pe,property);
var constantReference = Expression.Constant(value);
var ret = Expression.Lambda<Func<TSource, bool>>
(Expression.Equal(propertyReference, constantReference), new[] { pe });
return ret.Compile();
}
当我调用函数时 SimpleFilter("JobCustomerID", 449152)
它
产量 (p => p.JobCustomerId == 449152)
这是正确的。
如果我手动将该条件放入我的 Linq 语句中,我会得到正确的 return。
var jj = db.VW_Job_List.Where((p => p.JobCustomerId == 449152));
然而,当通过过滤器函数调用时,Linq 抛出 OutOfMemoryException
。
它在我的应用程序中被称为:
var jj = db.VW_Job_List.Where(SimpleFilter<VW_Job_List>("JobCustomerID", 449152));
如果我使用文本标准调用该函数,它 return 是正确的:
var jj = db.VW_Job_List.Where(SimpleFilter<VW_Job_List>("CompanyCode", "LCS"));
关于使用需要容纳的整型变量有什么特别之处吗?我有什么编码不正确吗?任何想法或见解将不胜感激。
两次通话
var jj = db.VW_Job_List.Where((p => p.JobCustomerId == 449152));
和
var jj = db.VW_Job_List.Where(SimpleFilter<VW_Job_List>("JobCustomerID", 449152));
不等价。第一个解析为 Queryable.Where
,因此过滤器在数据库内部应用,而第二个解析为 Enumerable.Where
,从而导致将整个 table 加载到内存中并在那里应用过滤器。
问题是你的SimpleFilter
的return类型是Func<TSource, bool>
。为了使它们相等,应该是Expression<Func<TSource, bool>>
。请注意,尽管它们在视觉上看起来相同,但由于应用于 IQueryable<T>
.
时的重载分辨率不同,lambda 表达式和 lambda 委托之间存在巨大差异
所以,像这样改变方法再试一次:
public Expression<Func<TSource,bool>> SimpleFilter<TSource> (string property, object value)
{
var type = typeof(TSource);
var pe = Expression.Parameter(type, "p");
var propertyReference = Expression.Property(pe,property);
var constantReference = Expression.Constant(value);
var ret = Expression.Lambda<Func<TSource, bool>>
(Expression.Equal(propertyReference, constantReference), new[] { pe });
return ret; // No .Compile()
}
我是 Linq 的新手,也是表达式树的真正初学者。
我有一个通用的表达式例程,它构建了一个简单的 Linq where 子句,我在以下位置找到了它:
https://www.simple-talk.com/dotnet/net-framework/dynamic-linq-queries-with-expression-trees/
public Func<TSource,bool> SimpleFilter<TSource> (string property, object value)
{
var type = typeof(TSource);
var pe = Expression.Parameter(type, "p");
var propertyReference = Expression.Property(pe,property);
var constantReference = Expression.Constant(value);
var ret = Expression.Lambda<Func<TSource, bool>>
(Expression.Equal(propertyReference, constantReference), new[] { pe });
return ret.Compile();
}
当我调用函数时 SimpleFilter("JobCustomerID", 449152)
它
产量 (p => p.JobCustomerId == 449152)
这是正确的。
如果我手动将该条件放入我的 Linq 语句中,我会得到正确的 return。
var jj = db.VW_Job_List.Where((p => p.JobCustomerId == 449152));
然而,当通过过滤器函数调用时,Linq 抛出 OutOfMemoryException
。
它在我的应用程序中被称为:
var jj = db.VW_Job_List.Where(SimpleFilter<VW_Job_List>("JobCustomerID", 449152));
如果我使用文本标准调用该函数,它 return 是正确的:
var jj = db.VW_Job_List.Where(SimpleFilter<VW_Job_List>("CompanyCode", "LCS"));
关于使用需要容纳的整型变量有什么特别之处吗?我有什么编码不正确吗?任何想法或见解将不胜感激。
两次通话
var jj = db.VW_Job_List.Where((p => p.JobCustomerId == 449152));
和
var jj = db.VW_Job_List.Where(SimpleFilter<VW_Job_List>("JobCustomerID", 449152));
不等价。第一个解析为 Queryable.Where
,因此过滤器在数据库内部应用,而第二个解析为 Enumerable.Where
,从而导致将整个 table 加载到内存中并在那里应用过滤器。
问题是你的SimpleFilter
的return类型是Func<TSource, bool>
。为了使它们相等,应该是Expression<Func<TSource, bool>>
。请注意,尽管它们在视觉上看起来相同,但由于应用于 IQueryable<T>
.
所以,像这样改变方法再试一次:
public Expression<Func<TSource,bool>> SimpleFilter<TSource> (string property, object value)
{
var type = typeof(TSource);
var pe = Expression.Parameter(type, "p");
var propertyReference = Expression.Property(pe,property);
var constantReference = Expression.Constant(value);
var ret = Expression.Lambda<Func<TSource, bool>>
(Expression.Equal(propertyReference, constantReference), new[] { pe });
return ret; // No .Compile()
}