1. 程式人生 > >IEnumerable<T>和IQueryable<T>區分

IEnumerable<T>和IQueryable<T>區分

針對 pre alt list RR enum enume light n)

哎,看了那麽多,這個知識點還是得開一個文章

IQueryable和IEnumerable都是延時執行(Deferred Execution)的,而IList是即時執行(Eager Execution)

IQueryable和IEnumerable在每次執行時都必須連接數據庫讀取而IList讀取一次後,以後各次都不需連接數據庫。

前兩者很容易造成重復讀取,性能低下,並且可能引發數據不一致性

IQueryable弊端:當把查詢出來的數據,根據指定條件添加到其他表中時,會報連接以打開錯誤!原因:IQueryable在每次執行時都必須連接數據庫讀取,所以數據庫連接是一直開著的!

LINQ查詢方法一共提供了兩類擴展方法,在System.Linq命名空間下,有兩個靜態類:

    Enumerable類,它針對繼承了IEnumerable<T>接口的集合類進行擴展。

    Queryable類,它針對繼承了IQueryable<T>接口的集合類進行擴展。

接口IQueryable<T>實際也是繼承了IEnumerable<T>接口的,簡單的來表述就是:本地數據源用IEnumerable<T>,遠程數據源用IQueryable<T>。

LINQ查詢從功能上來講實際上可以分為三類:LINQ to OBJECTS、LINQ to SQL、LINQ to XML。設計Enumerable<T>和Queryable<T>兩套接口的原因是為了區別對待

LINQ to OBJECTS、LINQ to SQL,

針對LINQ to OBJECTS時,使用Enumerable中的擴展方法對本地集合進行排序和查詢等操作,查詢參數接受的是Func<>。

針對LINQ to SQL時,則使用Queryable中的擴展方法,它接受的參數是Expression<>。

LINQ to SQL引擎最終會將表達式樹轉化成為相應的SQL語句,然後在數據庫中執行。//表達式樹???啥jb

原文
在使用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.Expression是一個表達式,會存儲拼接表達式樹,直到在運行期最終執行。

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

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

我們需要將表達式組合好,然後再一起提交到數據庫執行,返回查詢結果。(那這句話的意思是在ef查詢中用Iqueryable接收)

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

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

這就是IQueryable的延遲加載把.


  

IEnumerable<T>和IQueryable<T>區分