C# IQueryable及IEnumerable區(qū)別解析
在使用EF查詢數(shù)據(jù)的時候,我們常用的查詢數(shù)據(jù)方式有l(wèi)inq to sql,linq to object,
查詢返回的結(jié)果有兩種類型:IQueryable、IEnumerable,兩者內(nèi)部的處理機制是完全不同的。
清楚認識,這里也是一個數(shù)據(jù)查詢的優(yōu)化點。
在System.linq命名空間,有兩個靜態(tài)類:Queryable和Enumerable.
在System.linq.Queryable中,參數(shù)接收的是一個表達式類型,返回IQueryable接口
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
在System.linq.Enumerable中,參數(shù)接收的是一個謂詞表達式,也就是一個委托
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
那么在查詢數(shù)據(jù)使用linq to object的時候,會根據(jù)傳遞的參數(shù)不同返回不同的類型.
1.where條件接收表達式,返回IQueryable接口
2.where條件接收一個謂詞表達式(委托)返回一個IEnumerable接口
那么什么時候用IQueryable<T>,什么時候用IEnumerable<T>?
1.Func<>謂詞表達式,就是一個委托,委托一旦調(diào)用,就立即執(zhí)行了,將執(zhí)行結(jié)果保存在內(nèi)存中。
2.Expression是一個表達式,會存儲拼接表達式樹,直到在運行期最終執(zhí)行。
那么在EF中我們根據(jù)條件查詢數(shù)據(jù)時,不應該把數(shù)據(jù)一次性加載到本地內(nèi)存中,然后再本地內(nèi)存中進行篩選,如果數(shù)據(jù)量大了,就崩潰了。
我們需要將表達式組合好,然后再一起提交到數(shù)據(jù)庫執(zhí)行,返回查詢結(jié)果。
(每次在執(zhí)行where查詢操作符的時候IQueryProvider會為我們創(chuàng)建一個新的IQueryable<T>,調(diào)用AsEnumerable()方法的時候并不會去實際取值,只是
得到了一個IEnumerable,所以EF在查詢數(shù)據(jù)時候不要先取IEnumerable再去篩選數(shù)據(jù)。執(zhí)行ToList方法時才會去真正調(diào)用迭代器GetEnumerator()
取值。真正取值時候,會去執(zhí)行IQueryProvider中的Excute方法.(解析表達式,然后執(zhí)行取得結(jié)果))
這就是IQueryable的延遲加載把.
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C#使用HtmlAgilityPack實現(xiàn)解析提取HTML內(nèi)容
HtmlAgilityPack是一個HTML解析類庫,這篇文章主要為大家詳細介紹了C#如何使用HtmlAgilityPack實現(xiàn)解析提取HTML內(nèi)容,感興趣的小伙伴可以參考一下2023-12-12