【问题标题】:Dynamic Linq where clause throws OutOfMemoryException动态 Linq where 子句抛出 OutOfMemoryException
【发布时间】:2016-12-07 20:26:24
【问题描述】:

我是 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 =&gt; p.JobCustomerId == 449152),这是正确的。

如果我在我的 Linq 语句中手动放置该条件,我会得到正确的返回。

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));

如果我使用文本标准调用该函数,它会正确返回:

var jj = db.VW_Job_List.Where(SimpleFilter<VW_Job_List>("CompanyCode", "LCS"));

对于使用需要适应的整数变量有什么特别的要求吗?我有什么东西编码不正确吗?任何想法或见解将不胜感激。

【问题讨论】:

  • 所以你查询数据库?如果是,VW_Job_List 表中有多少行?

标签: c# entity-framework linq expression-trees dynamic-linq


【解决方案1】:

两个电话

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,从而导致将整个表加载到内存中并在那里应用过滤器。

问题是您的SimpleFilter返回类型Func&lt;TSource, bool&gt;。为了使它们等效,它应该是Expression&lt;Func&lt;TSource, bool&gt;&gt;。请注意,尽管它们在外观上看起来相同,但由于应用于 IQueryable&lt;T&gt; 时的重载分辨率不同,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()
}

【讨论】:

  • 嗯,很有趣。我从来没有说过使用Expression&lt;...&gt; 和不使用 EF 之间的区别
  • 这可能会使我的 Web 应用程序免于性能下降。谢谢。
猜你喜欢
  • 2023-03-29
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多