【问题标题】:EF 6: The result of a query cannot be enumerated more than onceEF 6:一个查询的结果不能被多次枚举
【发布时间】:2013-12-18 16:40:13
【问题描述】:

不使用 ToList() 有什么方法可以避免“查询的结果不能被枚举多次”异常?

这是我的代码的简化版本:

var entities = _db.Trades.Where(t => t.A > 10);
int totalCount = entities.Count();
entities = entities.Where(t => t.B > 10);
int totalCountAfterAdditionalFilter = entities.Count();

出于性能考虑,我无法调用 ToList()。我知道我可以再生成一个 IQueryable,但这似乎是错误的(我有更多这样的过滤器)。在我第一次调用 Count() 之后,我能否以某种方式保留/复制 IQueryable?

谢谢!

【问题讨论】:

  • “由于性能方面的考虑,我不能打电话给ToList()”什么性能方面的考虑?查询需要在某个时候具体化 - 为什么不在 List 中?
  • 我有超过 100 万条记录。在这个阶段将它们全部加载到内存中似乎是错误的。在应用最终过滤器之前,我只想获得计数。过滤完成后,我将具体化查询,它将仅返回 10 条左右的记录。
  • 您真的需要知道这两个计数,还是只需要知道是否过滤掉了任何项目?你可以只过滤t.B <= 10,如果有任何项目,两者都不一样,你就有答案了。如果你真的需要完整的计数,那是行不通的。
  • Servy,在这种情况下,两个计数都需要

标签: c# entity-framework


【解决方案1】:

不,你不能像那样达到你想要的结果。但是,您也可以将过滤器保存到变量中,然后根据需要组合它们:

 Func<Trade, bool> filter1 = t => t.A > 10;
 Func<Trade, bool> filter2 = t => t => t.B > 10;
 Func<Trade, bool> compositeFilter = t => filter1(t) && filter2(t);

 int totalCount = _db.Trades.Count(filter1);
 int totalCountAfterAdditionalFilter  = _db.Trades.Count(compositeFilter);

 //Need more?
 compositeFilter = t => compositeFilter(t) && t.C > 100;
 int totalAfterMoreFilters = _db.Trades.Count(compositeFilter);

【讨论】:

  • 过滤器Funcs 是否必须包装在Expression&lt;T&gt; 中以供LINQ to Entities 使用?
  • 问题是我有两个以上的过滤器,其中一些不应该被触发。但我喜欢你的想法。也许我需要找到一种方法来动态生成表达式,将其保存到变量中然后重用它。
【解决方案2】:

可能是:

Trades.Where(x => x.A > 10).Select(x => new { i = 1, j = x.B > 10 ? 1 : 0}).
    GroupBy(y => y.i).
    Select(g => new { c = g.Count(), = g.Sum(z => z.j)})

这就是在一个查询中为您提供 2 个信息。

【讨论】:

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