2010-12-10 60 views
6

編寫一個自定義LINQ提供者而不是寫一個實現IEnumerable的簡單類的好處是什麼?爲什麼寫一個自定義的LINQ提供程序?

例如,這quesiton顯示Linq2Excel:

var book = new ExcelQueryFactory(@"C:\Users.xls"); 
var administrators = from x in book.Worksheet<User>() 
        where x.Role == "Administrator" 
        select x; 

但什麼是比 「天真」 的實施爲IEnumerable好處?

+0

不確定爲什麼linq-to-excel從IQueryable中獲利,但有些情況會使代碼更快。 – CodesInChaos 2010-12-10 16:41:06

回答

11

Linq提供程序的目的是基本上將Linq表達式樹(它們構建在查詢的後面)轉換爲數據源的本地查詢語言。在數據已經在內存中的情況下,您不需要Linq提供程序; Linq 2對象很好。但是,如果您正在使用Linq與外部數據存儲(如DBMS或雲)進行對話,則這是絕對必要的。

任何查詢結構的基本前提是數據源的引擎應該儘可能地做大量的工作,並且只返回客戶端需要的數據。這是因爲數據源被假定爲最好地知道如何管理其存儲的數據,並且因爲數據的網絡傳輸在時間上相對昂貴,因此應該最小化。現在,實際上,第二部分是「僅返回客戶請求的數據」;服務器不能讀取你的程序的頭腦,並知道它真的需要什麼;它只能提供它的要求。這是一個智能的Linq提供者絕對會吹走一個「天真」的實現。使用生成表達式樹的Linq的IQueryable端,Linq提供者可以將表達式樹轉換成SQL語句,DBMS將使用該語句返回客戶端在Linq語句中要求的記錄。一個幼稚的實現需要使用一些廣泛的SQL語句來檢索所有記錄,以便向客戶端提供內存對象列表,然後所有的篩選,分組,排序等工作都由客戶端完成。

例如,假設您正在使用Linq從其主鍵的DB表中獲取記錄。一個Linq提供者可以將dataSource.Query<MyObject>().Where(x=>x.Id == 1234).FirstOrDefault()轉換成「SELECT TOP 1 * from MyObjectTable WHERE Id = 1234」。這會返回零個或一個記錄。一個「天真」的實現可能會向服務器發送查詢「SELECT * FROM MyObjectTable」,然後使用Linq的IEnumerable端(對內存類起作用)進行過濾。在一份聲明中,您希望從一張擁有1000萬條記錄的表格中產生0-1個結果,您認爲哪些方法可以更快地完成這項工作(甚至可以工作,而不會耗盡內存)?

7

如果你只是想爲你的目的使用LINQ-to-Objects(即類似foreach)的功能,那麼你不需要編寫LINQ提供程序,它主要針對內存列表。

需要編寫一個LINQ提供程序,如果你想分析查詢的表達式樹,以便將它翻譯成別的東西,比如SQL。例如,您提到的ExcelQueryFactory似乎可以與OLEDB-Connection一起使用。這可能意味着在查詢數據時不需要將整個excel文件加載到內存中。

3

總體表現。如果你有某種索引,你可以比簡單的IEnumerable<T>更快地進行查詢。

Linq-To-Sql就是一個很好的例子。在這裏,您將linq語句轉換爲另一個語句,以供SQL服務器理解。因此,服務器將執行過濾,排序......使用索引,並不需要將整個表格發送給客戶端,然後使用linq-to-objects來完成。

但也有更簡單的情況下,它可以是太有用:

如果你有一棵樹指數在屬性格式Time然後像.Where(x=>(x.Time>=now)&&(x.Time<=tomorrow))範圍查詢可以優化了很多,並不需要遍歷枚舉中的每一項。

1

LINQ將盡可能提供延遲執行以提高性能。

IEnumurable <>和IQueryable <>將完全提供不同的程序實現。 IQueryable將通過動態構建表達式樹來提供本機查詢,這確實提供了良好的性能,然後是IEnumurable。

http://msdn.microsoft.com/en-us/vcsharp/ff963710.aspx

如果我們不相信我們可以使用var關鍵字和動態它將初始化一個最合適的類型。

相關問題