1. 程式人生 > >C# IQueryable和IEnumerable的區別

C# IQueryable和IEnumerable的區別

機制 ide rep lan 處理機 about tools 數據庫 provider

原文地址:http://blog.csdn.net/q646926099/article/details/52297897

在使用EF查詢數據的時候,我們常用的查詢數據方式有linq to sql,linq to object,

查詢返回的結果有兩種類型:IQueryable、IEnumerable,兩者內部的處理機制是完全不同的。

清楚認識,這裏也是一個數據查詢的優化點。

在System.linq命名空間,有兩個靜態類:Queryable和Enumerable.

在System.linq.Queryable中,參數接收的是一個表達式類型,返回IQueryable接口

[csharp] view plain copy print?
  1. public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

在System.linq.Enumerable中,參數接收的是一個謂詞表達式,也就是一個委托

[csharp] view plain copy print?
  1. public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
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的延遲加載把.

C# IQueryable和IEnumerable的區別