【轉】【More Effective C#】IEnumerable和IQueryable的那點事
IEnumerable,IQueryable之前世今生
IEnumerable<T>在.Net2.0中我們已經很熟悉了。你想要利用Foreach迭代嗎?實現IEnumerable<T>吧!你想直接做為數據源綁定到控件嗎?使用IEnumerable吧!是的,只要是序列它都實現了IEnumerable<T>(.Net1.0下的序列類除外)。除了這些,LINQ的出現還賦予了IEnumerable<T>更強悍的功能。IQueryable<T>繼承IEnumerable<T>,詳細看IEnumerable<T>和IQueryable<T>這兩個API的簽名可以說非常相似,從某種意義上來說它們是可以互換的,但是卻不總是可以互相代替的。IEnumerable<T>和IQueryable<T>的行為有所不同,其性能方面也可能天差地別。例如:
var q = from c in dbContext.Customers
where c.City == "shenzhen"
select c;
var q = (from c in dbContext.Customers
where c.City == "shenzhen"
select c).AsEnumerable();
這兩個查詢看起來幾乎一模一樣,查詢返回的結果也一樣,但他們的實現方式卻大相徑庭。第一個查詢使用了LINQ2SQL的處理方式,第二個查詢則使用了LINQ2Object處理。通過前面的學習我們知道,LINQ2Object的處理結果是把LINQ表達式映射成對應的委托,而LINQ2SQL則是保存了一系列的"步驟"---表達式樹的處理方式,兩者的區別簡單的理解就是LINQ2Object將數據存放在內存中而LINQ2SQL則是把數據存放在遠程的服務器中。
場景模擬
舉一個例子,現在有兩個水果批發商A,B..A除了是批發商自己還承包了幾個果場,自產自銷,B和幾個大型的果場合作,只做批發工作。每次客人來A訂貨,指定要什么貨物,A就可以立刻拿出,速度快服務佳,缺點是由于是自己的果場,那量肯定不大,而且品種不齊全。小作坊式的經營B呢?每次客戶訂單,B是先把客戶需要的貨物規格等記錄下來,一次性去各個果場取貨,這樣B的優點就是量大,品種多,但速度可能偏慢(收到貨的時間)。不過若B以A的銷售方式來銷售,那么B的效績肯定是讓人十分不滿意,工廠式的經營。
總結之,IEnumerable<T>查詢必須在本地執行,并且執行查詢前我們必須把所有的數據加載到本地,而且更多的時候加載的數據有大量的數據是我們不需要的無效數據,但是我們卻不得不傳輸更多的數據,做更多的無用功。而IQueryable<T>卻總能只提供你所需要的數據,大大減少了數據的傳輸,這就好比我們在小作坊下訂單,小作坊老板跟我們說他的貨剛好比你所需要的多出一些,你只能要了它,不然剩下一點他不好賣等等,而大工廠卻不會出現這種狀況。
個性要求
雖說小作坊很多弊病,但有時候卻有著大工廠無法媲美的服務,假如你需要一種八種水果組合套餐,大工廠一般不會為你量身定做單對單服務,相反,小作坊客源有限,一般都會滿足你的個人需求。
場景切換:在<<[More Effective C#]Lambda表達式優化>>里我們提到過LINQ2SQL中是不允許出現自定義方法的,這是由于LINQ2SQL的處理方式.詳見<<[More Effective C#]Lambda表達式優化>>,而LINQ2Object卻能很好的滿足我們自定義方法這個性化的要求。
但是除了自定義方法還有一些內置的方法IEnumerable<T>和IQueryable<T>是同時支持的,例如常見的string類的操作方法substring、indexof等等。
尾聲
可能這個例子在這里有些牽強,但相信IEnumerable<T>和IQueryable<T>之間的區別不難理解。更多時候我們在查詢序列的時候要考慮到底是本地查詢好還是遠程查詢好,至于哪種查詢更好沒有絕對的說法,適合應用環境,已經能發揮最大效應的那就是最好的。
注:本文轉自 http://www.dotblogs.com.tw/kongyiyun/archive/2010/10/22/18510.aspx

浙公網安備 33010602011771號