IQueryable和IEnumerable以及AsEnumerable()和ToList()的區別
阿新 • • 發佈:2018-11-11
注意:本文背景為 Linq to sql 。文中ie
指代IEnumerable
,iq
指代IQueryable
。
IQueryable 和 IEnumerable 的區別
-
IQueryable
延時執行;擴充套件方法接受的是Expression(必須要能轉成sql,否則報錯) -
IEnumerable
延時執行;擴充套件方法接受的是Func(C#語法)
AsEnumerable() 和 ToList() 的區別
-
ToList()
立即執行,載入資料到記憶體中。 -
AsEnumerable()
延遲執行,真正使用時才載入資料。
對IQueryable物件使用AsEnumerable()後,仍然是延遲執行,不過此時物件本質已經變了。
前面已經說了IEnumerable的擴充套件方法接受的是Func(C#語法)
1.它會把iq物件(轉變之前的)的擴充套件方法翻譯成sql語句,查詢出資料載入到記憶體中,變為ie物件;
2.此時再把ie物件(轉變之後的)的擴充套件方法,使用C#求解,得到最終結果。
例如:iq物件的Skip、Take方法,會被翻譯成sql,在資料庫裡執行取出最終結果。
而ie物件的Skip、Take方法,則會取出全部資料到記憶體中,在記憶體中執行Skip、Take,會耗費大量資源。
誤區
- 誤區1:對 iq物件 和 ie物件 使用foreach時,對於迴圈的每項都要查詢資料庫。
錯誤!
foreach針對的是資料集整體物件
結論
假設我們把最終資料之前的資料稱為中間資料,那麼:
- 當中間資料只是作為條件篩選,需要的只是層層篩選之後的最終資料時,應該繼續使用IQueryable,防止載入不必要的資料到記憶體中。
- 當存在中間資料,且中間資料被重複使用時,應該使用IQueryable.ToList()立即載入到記憶體裡使用(都被重複使用了,應該叫做最終資料了吧..);
- 如果中間結果無用,且想對IQueryable物件使用Func(C#語法)的擴充套件方法
參考
- LINQ查詢中的IEnumerable<T>和IQueryable<T>
- LINQ使用細節之.AsEnumerable()和.ToList()的區別
- 建議29:區別LINQ查詢中的IEnumerable<T>和IQueryable<T> - 陸敏技《編寫高質量程式碼改善C#程式的157個建議》