2013-01-09 40 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()不被視爲強制執行......它們是查詢的一部分......我想。