C# IQueryable和IEnumerable的區別
在使用EF查詢資料的時候,我們常用的查詢資料方式有linq to sql,linq to object,
查詢返回的結果有兩種型別:IQueryable、IEnumerable,兩者內部的處理機制是完全不同的。
清楚認識,這裡也是一個數據查詢的優化點。
在System.linq名稱空間,有兩個靜態類:Queryable和Enumerable.
在System.linq.Queryable中,引數接收的是一個表示式型別,返回IQueryable介面
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
在System.linq.Enumerable中,引數接收的是一個謂詞表達式,也就是一個委託
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
那麼在查詢資料使用linq to object的時候,會根據傳遞的引數不同返回不同的型別.
1.where條件接收表示式,返回IQueryable介面
2.where條件接收一個謂詞表達式(委託)返回一個IEnumerable介面
那麼什麼時候用IQueryable<T>,什麼時候用IEnumerable<T>?
1.Func<>謂詞表達式,就是一個委託,委託一旦呼叫,就立即執行了,將執行結果儲存在記憶體中。
2.Expression是一個表示式,會儲存拼接表示式樹,直到在執行期最終執行。
那麼在EF中我們根據條件查詢資料時,不應該把資料一次性載入到本地記憶體中,然後再本地記憶體中進行篩選,如果資料量大了,就崩潰了。
我們需要將表示式組合好,然後再一起提交到資料庫執行,返回查詢結果。
(每次在執行where查詢操作符的時候IQueryProvider會為我們建立一個新的IQueryable<T>,呼叫AsEnumerable()方法的時候並不會去實際取值,只是
得到了一個IEnumerable,所以EF在查詢資料時候不要先取IEnumerable再去篩選資料。執行ToList方法時才會去真正呼叫迭代器GetEnumerator()
取值。真正取值時候,會去執行IQueryProvider中的Excute方法.(解析表示式,然後執行取得結果))
這就是IQueryable的延遲載入把.