使用forEach迭代IQueryable与调用ToList()然后执行forEach - performance

时间:2016-06-10 09:36:44

标签: c# entity-framework linq linq-to-sql

我一直在看一个课程,作者提到如果你有一些可以说的话,请说:

var someQuery = dbContext.Table.Where(x => x.Name == "Mark");

然后尝试使用someQuery迭代forEach的结果,它保持数据库连接打开,直到整个forEach结束,并且很多初学者开发者犯了这个错误在forEach中做了很多逻辑。相反,她建议先预先调用toList(),然后对内存中的集合执行forEach

我找不到任何关于此的参考,但实体框架会保持数据库处于打开状态,直到forEach循环停止。我如何评估这是否真的符合性能?

1 个答案:

答案 0 :(得分:5)

应用于ToList()的{​​{1}}方法是一种扩展方法,您可以在带有.NET反编译器的System.core.dll中看到该方法; 该方法复制&#34;私有数组&#34;如果源是IQueryable<T>,否则它将从源执行foreach循环。

ICollection<T>的真实实现是IQueryable<T>,而不是System.Data.Entity.Infrastructure.DbQuery<TResult>

因此,ICollection<T>基本上使用ToList()复制来源。

现在,它取决于实现,但是以EF核心为例,有一个Enumerator class,您可以看到在处理类时Connection(foreach)已关闭。 根据另一个answer和ms documentation,您应该尽快释放连接并使其在连接池中可用,从而关闭连接。

  

为每个唯一连接字符串创建连接池。创建池时,会创建多个连接对象并将其添加到池中,以满足最小池大小要求。根据需要将连接添加到池中,直到指定的最大池大小(默认值为100)。当关闭或处置时,连接将被释放回池中。

因此,如果您正在执行复杂操作或执行其他查询或foreach中的任何其他内容,则首选ToList。