2011-07-23 76 views
9

我正在嘗試創建一個LINQ提供程序。我正在使用指南LINQ: Building an IQueryable provider series,並且我已將代碼添加到LINQ:構建IQueryable提供程序 - 第IV部分。LINQ表達式如何知道Where()在Select()之前?

我感覺到它是如何工作的,以及它背後的想法。現在我被困在一個問題上,這不是一個代碼問題,而是更多關於理解的問題。

我發射了這一說法:

QueryProvider provider = new DbQueryProvider(); 
Query<Customer> customers = new Query<Customer>(provider); 

int i = 3; 
var newLinqCustomer = customers.Select(c => new { c.Id, c.Name}).Where(p => p.Id == 2 | p.Id == i).ToList(); 

莫名其妙的代碼,或表情,知道,Where而來的Select之前。但是如何以及在哪裏?

在調試模式下,對錶達式進行排序的代碼沒有辦法,實際上ToString()顯示在Select之前出現在Where之前。

我試圖讓代碼失敗。正常情況下,我先做了Where,然後再做了Select

那麼表達式如何排序呢?我沒有對指南中的代碼進行任何更改。

+0

你是什麼意思「選擇前的位置」?你的意思是在生成的SQL? – svick

+0

我能想到的唯一的事情是,也許你看到生成的SQL有SELECT和WHERE重新排序?在這種情況下,我猜想在Linq2Sql提供程序中有一個優化步驟,它需要'SELECT Id,Name FROM(SELECT Id,Name FROM Customer WHERE Id = 2 || Id = @ i)'並將其轉換爲'SELECT Id,姓名從客戶那裏Id = 2 || Id = @ i' - 但這是你所看到的,這是你問什麼? – Stuart

+0

你知道[re-linq](http://relinq.codeplex.com/),對吧?你不是在重新發明輪子,我希望:-) – xanatos

回答

10

的計算公式是「解釋」,「翻譯」或爲了你寫他們「執行」 - 這樣的Where有,如果你執行前Select


來:

 var newLinqCustomer = customers.Select(c => new { c.Id, c.Name}) 
             .Where(p => p.Id == 2 | p.Id == i).ToList(); 

然後在匿名類型的IEnumerableIQueryable上執行Where


如果執行:

 var newLinqCustomer = customers.Where(p => p.Id == 2 | p.Id == i) 
             .Select(c => new { c.Id, c.Name}).ToList(); 

然後Where是在IEnumerable或客戶類型的IQueryable執行。


我能想到的唯一的事情是,你可能會看到一些生成的SQL,其中SELECT和WHERE被重新排序?在這種情況下,我猜想在(LINQ to SQL)供應商中有一個優化步驟需要SELECT Id, Name FROM (SELECT Id, Name FROM Customer WHERE Id=2 || [email protected])並將其轉換爲SELECT Id, Name FROM Customer WHERE Id=2 || [email protected] - 但這必須是提供商特定的優化。

+0

我不明白答案。 「在IQueryable上執行」和「在LinqToSQL中執行」有什麼不同? – svick

+0

對不起 - 現在整理它。正如我在對這個問題的評論中所說的,我只能想象OP會看到他正在研究的任何linq提供者進行的一些優化 - 但是我們沒有他的問題中的詳細信息。 – Stuart

+0

如果選擇過濾器在我之前被觸發,我必須啓用在代碼中看到它,通過一個斷點,但我不能。 你說,如果我先做選擇,那麼匿名類型在哪裏做,但是沒有名稱的方法調用選擇該怎麼做? I –

4

不,在一般情況下(如LINQ to Objects)select將在where語句之前執行。想想這是一個管道,你的第一步是一個轉化,第二個是過濾器。相反,如果你寫了Where ... Select,情況就是這樣。現在

,一個LINQ提供者已經走表達式樹和優化它,因爲它認爲合適的自由。請注意,您可能不會更改表達式的語義。這意味着智能提供商會嘗試將盡可能多的where子句放入SQL查詢中,以減少通過網絡傳輸的數據量。但是,請記住the example from Stuart:並非所有查詢提供者都很聰明,部分原因是排除查詢重新排序的副作用並不像看起來那麼容易。

+0

我不認爲你的第一段是正確的。 'Select'和'Where'子句只是投影和過濾器,爲了保留語義,它們必須按給定的順序發生。沒有「一般情況」,一個在另一個之前發生。它以任何原始查詢的順序編寫。 – Enigmativity

相關問題