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

cll*_*pse 12 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)


...但是如果我在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
}
Run Code Online (Sandbox Code Playgroud)

Amy*_*y B 12

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

这些都是推迟的.它们定义但不执行操作.

source.AsEnumerable
source.Select
source.Where
Run Code Online (Sandbox Code Playgroud)

这些枚举源,因此不推迟.

source.ToList
source.First
source.Single
foreach(var x in source)
Run Code Online (Sandbox Code Playgroud)

  • 我可以.什么? (5认同)

Net*_*ide 9

在您键入之前,它不会从数据库中获取所有项目

 ToList or First or Single
Run Code Online (Sandbox Code Playgroud)

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

  • 他正在查询数据表,而不是Linq DataContext或ObjectContext.对数据表的查询无法导致数据库查询执行 (2认同)
  • 是的,你是对的.但这是了解linq对方法的作用的一般解释.对于每个项目,每个语句之前需要一些时间来获取数据而不是使用ToList. (2认同)