在LINQ查询上缓慢的foreach() - ToList()极大地提升了性能 - 为什么会这样?

时间:2010-08-26 14:05:52

标签: c# linq

我有点把握整个延迟执行的概念,但以下让我感到困惑......

在包含大约1000行的DataTable上,我调用 AsEnumerable()。然后我选择返回到强类型类IEnumerable中的实体(1) ...这里我感到困惑:我在集合上做了一个foreach循环;使用一堆 Where()调用(2)来从集合中的各个项目中选择东西...而且它已经慢了。

  1. DataTable.AsEnumerable().Select(r => new ObjectRepresentation { ... });
  2. item.Where(i => i.SomeEnum == SomeEnum.Something)

  3. ...但是如果我在DataTable上的 AsEnumerable()调用之后立即调用 ToList(),则foreach循环只需不到一秒钟即可完成。

    我在这里缺少什么?我每次循环迭代时是否有效地调用 AsEnumerable()?或者每次我访问集合中的项目?或者每次我对集合中的项目进行 Where()调用?或者以上所有?


    更新

    一些完整的代码:

    public class ObjectRepresentation
    {
        public SomeEnum SomeEnum { get; set; }
    }
    
    
    var collection = DataTable.AsEnumerable().Select(r => new ObjectRepresentation
    {
        SomeEnum = (SomeEnum)Convert.ToInt32(r["SomeEnum"])
    });
    
    foreach(var item in collection) // slow loop
    {
        // 10 or so Where() calls on item inside this loop
    }
    
    collection = collection.ToList(); // Hit hyper speed button!
    
    foreach(var item in collection) // fast loop
    {
        // 10 or so Where() calls on item inside this loop
    }
    

3 个答案:

答案 0 :(得分:11)

您不了解哪些方法被延迟,哪些方法没有延迟,因此您无法理解代码何时定义操作与执行操作。

这些都是延期的。它们定义但不执行操作。

source.AsEnumerable
source.Select
source.Where

这些枚举来源,因此不会延期。

source.ToList
source.First
source.Single
foreach(var x in source)

答案 1 :(得分:8)

在您输入

之前,它不会从数据库中获取所有项目
 ToList or First or Single

在foreach中,您将为每个项目向数据库发送查询。所以它工作得更慢。打开你的sql profiler以更好地理解。

答案 2 :(得分:0)

实际上,您似乎并不清楚什么是代码执行,以及在实际使用结果后(可能)稍后执行的意图的定义是什么。我建议阅读LINQ的这一部分。

并且可能尝试使用附加的调试器执行两个变体,这样您就可以实际查看正在执行的代码以及数据实际发生的情况。你可能会在这里遇到一个(大?)惊喜......