2013-01-09 15 views
4
  var costCenters = from c in dbContext.CostCenters //no sql call here 
          orderby c.DisplayRank descending 
          select c; 


      List<CostCenter> lstCostCenter = costCenters.ToList();//Immediate execution to sql the first time 

      lstCostCenter = costCenters.ToList();//no Sql call ?? 

      int test = costCenters.Count();//Call Sql everytime 
      test = costCenters.Count();//Call Sql again??? 

我使用实体框架5如何识别哪些Linq函数不会多次调用sql?

我开始学习LINQ的。我真的很困惑,哪些即时执行函数每次都会调用SQL。正如你在上面的示例中看到的,ToList()和Count()都是立即执行函数,但是只有Count()会在子序列调用上连接到sql。 ToList()连接到sql 1次,但Count()将每次连接到Sql。
如何识别哪些linq函数不会多次调用sql?

回答

3

的区别是你第一次调用ToList()它转换的IQueryable(这仅仅是一个查询的定义)的IEnumerable列表(查询数据库)。换句话说,您将获取现在在内存中的对象列表,因此结果列表中的任何进一步LINQ调用都会使用与内存中对象配合使用的IEnumerable版本。此外,EF具有缓存结果的功能,因此即使您在原始IQueryable引用上调用ToList,也可能使用内存中的对象,而不是从数据库中获取它们。我猜测是伯爵再次命中,而不是计数缓存的结果数据库,因为数查询是不是为ToList相同的查询(它是一种聚合/分组),也或许正是这样设计的因为数据库引擎在提供计数方面效率更高。

在你的榜样,costCenters是一个IQueryable,因为你要做的就是定义查询,但不叫ToList呢。 lstCostCenter是IEnumerable,用ToList执行后表示查询中的内存中结果。在IQueryable上执行时,通常会产生结果的立即调用,.Count,.ToList等将导致数据库调用(例外情况是当它找到可以重用的缓存结果时),并调用IEnumerable对象(在您的情况下lstCostCenter)将在内存中运行。

为了获得更多的可预见的结果,则首先调用ToList上的IQueryable,并作出了IEnumerable所有后续调用。换句话说,您拨打lstCostCenter的任何内容都可以保证不会触及数据库。这通常是处理它的最好方法,除非您希望得到的列表很大。例如,如果lstCostCenter以10,000个对象结束,那么您可能不会想要执行lstCostCenter.Where(x=>x.Blah > 5),因为它会遍历内存中的所有10,000个对象来过滤它们。在这种情况下,最好先修改查询,方法是将附加调用添加到IQueryable中,然后调用ToList,以便我们利用DB引擎更好地处理大集合:costCenters.Where(x=>x.Blah > 5).ToList()

+0

进一步阅读后,我意识到缓存是由“强制执行” – gavin

4

首先,ToList()从不使用延迟执行。它总是实现信息的马上。它不会每次都返回数据库,因为它已经抓住了所有的实体。

要知道哪个运营商做什么,只是看看at this link

+0

从你给我的链接,都ToList()和COUNT()被归类为立即执行。从网站:立即执行意味着数据源被读取并且操作在声明查询的代码中的位置执行。所有返回单个不可枚举结果的标准查询操作符立即执行。那么每次调用ToList()和Count()都不应该调用sql吗? – gavin

+0

不是ToList,不是,因为它需要做的就是自己抓取所有的记录。一旦加载了所有记录,EF就知道不会回到SQL,因为查询已经被加载。 – IronMan84

+1

+1链接 –

1

http://msdn.microsoft.com/en-us/library/bb738633.aspx

的区别在于 “强制执行”。如果强制立即执行查询,则缓存结果。而ToList(),ToArray()等转换运算符甚至被分类为强制执行,所以进一步的调用只能在内存缓存中运行。 Count(),First(),Max()和Average()不被视为强制执行......它们是查询的一部分......我想。