C# IQueryable和IEnumerable的區別


IEnumerable<T> 泛型類在調用自己的SKip 和 Take 等擴展方法之前數據就已經加載在本地內存里了,而IQueryable<T> 是將Skip ,take 這些方法表達式翻譯成T-SQL語句之后再向SQL服務器發送命令。也是延遲在我要真正顯示數據的時候才執行。

LINQ查詢一共提供了兩類擴展方法,在System.Linq命名空間下,有兩個靜態類:Enumerable類,它針對繼承了IEnumerable<T>接口的集合進行擴展;Queryable類,它針對繼承了IQueryable<T>接口的集合類進行擴扎。接口IQueryable<T>也是繼承了IEnumerable<T>接口的,所以,致使兩個接口的方法在很大程度上時一致的。

 

LINQ查詢從功能上來講實際上可分為3類:LINQ to OBJECTS、LINQ to SQL、LINQ to XML。設計兩套接口的目的在於區分對待LINQ to OBJECTS、LINQ to SQL,兩者對於查詢的處理在內部使用的是完全不同的機制。針對LINQ to OBJECTS時,使用Enumerable中的擴展方法對本地集合進行排序和查詢等操作,查詢參數接受的是Func<>。Func<>叫做謂語表達式,相當於一個委托。針對LINQ to SQL時,則使用Queryable中的擴展方法,它接受的是Expression<>。Expression<>用於包裝Func<>。LINQ to SQL最終會將表達式樹轉換成相應的SQL語句,然后在數據庫中執行。

 

簡單的說:本地數據源用IEnumerable<T>,遠程數據源用IQueryable<T>。

1.Func<>謂詞表達式,就是一個委托,委托一旦調用,就立即執行了,將執行結果保存在內存中。

2.Expression是一個表達式,會存儲拼接表達式樹,直到在運行期最終執行。

那么在EF中我們根據條件查詢數據時,不應該把數據一次性加載到本地內存中,然后再本地內存中進行篩選,如果數據量大了,就崩潰了。

我們需要將表達式組合好,然后再一起提交到數據庫執行,返回查詢結果。

(每次在執行where查詢操作符的時候IQueryProvider會為我們創建一個新的IQueryable<T>,調用AsEnumerable()方法的時候並不會去實際取值,只是

得到了一個IEnumerable,所以EF在查詢數據時候不要先取IEnumerable再去篩選數據。執行ToList方法時才會去真正調用迭代器GetEnumerator()
取值。真正取值時候,會去執行IQueryProvider中的Excute方法.(解析表達式,然后執行取得結果))

這就是IQueryable的延遲加載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM