【发布时间】:2010-08-26 14:05:52
【问题描述】:
我有点理解整个延迟执行的概念,但以下让我感到困惑......
在包含大约 1000 行的 DataTable 上,我调用 AsEnumerable()。然后,我选择返回到强类型类的 IEnumerable 中的实体 (1)... 这就是我感到困惑的地方:我在集合上执行了一个 foreach 循环;使用一堆 Where() 调用 (2) 从集合中的各个项目中选择东西......而且速度非常慢。
DataTable.AsEnumerable().Select(r => new ObjectRepresentation { ... });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
}
【问题讨论】:
-
听起来您在每次迭代时都在进行数据库调用。您可以运行 SQL Profiler 来查看是否属实...
-
为什么要调用 AsEnumerable()?如果 AsEnumerable 已实现 IEnumerable
,则 AsEnumerable 在编译时将对象更改为 IEnumerable 。为什么不使用表的 Rows 属性来迭代行? -
@Wix:
DataTable尚未实现IEnumerable<T>。当您在DataTable上调用AsEnumerable时,您调用的是DataTableExtensions.AsEnumerable方法,不是Enumerable.AsEnumerable。 msdn.microsoft.com/en-us/library/… -
嗯...您在抱怨 foreach 速度很慢...但您从未真正向我们展示过 foreach。给我们看一些更完整的代码,我们也许可以让它更快……
-
在你的问题中你说 但是如果我打电话给
ToList()我的AsEnumerable()(这对我来说是一个有趣的问题) ,但是在您的代码中,您在Select之后调用ToList,而不是AsEnumerable(我认为这完全是关于延迟执行 - 查询一遍又一遍地运行)。但是如果没有在foreach代码中看到item上的Where,就很难给出一个确定的答案。你能告诉我们Where是如何在foreach中被调用的吗(特别是因为ObjectRepresentation不是IEnumerable<T>)?很可能您在collection变量上调用Where!