1. 程式人生 > >Linq中 AsQueryable(), AsEnumerable()和ToList()的區別和用法

Linq中 AsQueryable(), AsEnumerable()和ToList()的區別和用法

Linq中 AsQueryable(), AsEnumerable()和ToList()的區別和用法:
在寫LINQ語句的時候,往往會看到AsEnumerable() ,AsQueryable() 和ToList()的用法,三者有何區別呢?以下是我的理解,有毛病請大家指教!
在System.Linq名稱空間下,有兩個靜態類:
Enumerable類,它針對繼承了IEnumerable<T>介面的集合進行擴充套件;
Queryable類,針對繼承了IQueryable<T>介面的集合進行擴充套件。
一、AsQueryable():
先說說什麼是 IQueryable,AsQueryable將一個序列向下轉換為一個IQueryable, 它生成了一個本地查詢的IQueryable包裝。
1,lazy load 特性
以下是一段最常見的程式碼:
var products = db.Product.where(p => p.Type == "food").select(p => new { p.Id, p.Name, p.CreateTime});
注意: Select() 的返回型別為 IQueryable
,為 IQueryable<T>, 語句執行後不會立刻查詢資料庫, 而是在迭代使用 products 時才會查資料庫, 具有 lazy load 的特性, 按需查資料庫可提高程式效率。
2,高程式效率.
迭代時上面的程式碼類似於下面的 sql 語句:
select Id, Name, CreateTime from Product where Type = 'food'
對 products 再次使用資料庫查詢操作, 執行時會把結果合併為1條 sql 語句, 如下,
var products = db.Product.where(p => p.Type == "food").select(p => new { p.Id, p.Name, p.CreateTime}); var orderedProducts = products.OrderBy(p => p.CreateTime);
迭代時生成的 sql 語句類似:
select Id, Name, CreateTime from Product where Type = 'food' order by CreateTime
IQueryable 有諸多限制, 只支援資料庫查詢語法, 無法支援 Linq to object 的操作, 是LINQ TO SQL。
結論
:AsQueryable將一個序列向下轉換為一個IQueryable, 它生成了一個本地查詢的IQueryable包裝。   二、AsEnumerable()
同樣支援 lazy load,是延遲執行的,實際上什麼都沒有發生,當真正使用物件的時候(例如呼叫:First, Single, ToList....的時候)才執行。 但不要濫用。迭代時遇到 AsEnumerable() 會先進行 sql 查詢, 但是, 千萬不要為了方便而濫用 AsEnumerable(), 可能會嚴重消耗資源,能進行 Linq to object 操作。
eg:var products = db.Product.AsEnumerable().Select(p => new {p.Id, p.Name, p.CreateTime.Date}); 對IQueryable物件使用AsEnumerable()後,仍然是延遲執行,不過此時物件本質已經變了。
上面的程式碼在查詢時會把整個Product表的結果存放進記憶體, 然後進行 .Select 查詢,嚴重消耗資源。
結論
:AsEnumerable將一個序列向上轉換為一個IEnumerable, 強制將Enumerable類下面的查詢操作符繫結到後續的子查詢當中。 AsEnumerable()延遲執行,不會立即執行。當你呼叫.AsEnumerable()的時候,實際上什麼都沒有發生。   注意: IQueryable實現了IEnumberable介面。但IEnumerable<T> 換成IQueryable<T>後速度提高很多。
IQueryable介面與IEnumberable介面的區別:  IEnumerable<T> 泛型類在呼叫自己的SKip 和 Take 等擴充套件方法之前資料就已經載入在本地記憶體裡了,而IQueryable<T> 是將Skip ,take 這些方法表示式翻譯成T-SQL語句之後再向SQL伺服器傳送命令,它並不是把所有資料都載入到記憶體裡來才進行條件過濾。   三、ToList()
呼叫 ToList() 會立刻查詢並儲存結果, 而不會等到迭代時才查詢,作用和 lazy load 是相反的。
在需要得到完整結果後, 再處理的場景, 需要使用 ToList()。