2009-01-27 63 views
1

我有一個Task對象,它具有Label對象的集合...在數據庫中,這些表格被稱爲Task和Label。如何在LINQ的表達式樹中創建連接?

有多種方式來搜索任務,因此,使用LINQ,我構建一個表達式樹......類似下面的代碼示例我的LINQ查詢:

IQueryable<Data.Task> query = ctx.DataContext.Tasks;  

if (criteria.Number > 0)  
    query = query.Where(row => row.Number == criteria.Number); 

if (criteria.CustomerId != Guid.Empty) 
    query = query.Where(row => row.Project.CustomerId == criteria.CustomerId); 

if (criteria.ProjectId != Guid.Empty) 
    query = query.Where(row => row.ProjectId == criteria.ProjectId); 

var data = query.Select(row => TaskInfo.FetchTaskInfo(row)); 

this.AddRange(data); 

這個偉大的工程。 ..但是現在我想要搜索具有特定標籤的任務,例如會計或功能請求。

我能夠從一個完整的查詢爲此在LINQPad:

from t in Tasks 
join l in Labels on t.TaskId equals l.SourceId 
where l.Name == "accounting" 
select t 

反正有沒有做到這一點使用表達式樹?我卡住了!任何幫助將不勝感激!

回答

4

我相信這應該這樣做:

Tasks.Join(Labels.Where(l => l.Name == "accounting"), t => t.TaskId, l => l.SourceId, (t, l) => t) 
+1

這樣做,但它不是原來的翻譯 - 它*更好*因爲它在連接之前做了什麼,但是我提供了一個翻譯,因此OP可以看到正常查詢翻譯中發生了什麼。 – 2009-01-27 21:50:48

5

A 「加入」(而不是 「加入...成」)在查詢表達式子句轉換成一個加入通話。棘手的一點是透明的標識符 - 只有一個序列來自連接,並且它必須同時具有tl(在你的例子中),所以編譯器有一定的魔力。

我沒有足夠的時間進入這裏的細節,但最好告訴你如何翻譯你的查詢表達式。

此:

from t in Tasks 
join l in Labels on t.TaskId equals l.SourceId 
where l.Name == "accounting" 
select t 

被翻譯成:

Tasks.Join(Labels, t => t.TaskId, l => l.SourceId, (t, l) => new { t, l }) 
    .Where(z => z.l.Name == "accounting") 
    .Select(z => z.t) 

注意引進 「Z」 的位置 - 基本上包含從原始表達式t和湖

編輯:大衛莫頓的答案給出了一個更有效的方式來做到這一點。他行等同於:

from t in Tasks 
join l in (from x in Labels where x.Name == "accounting") 
     on t.TaskId equals l.SourceId 
select t 

如果你只有加入後選擇條款,編譯器能夠跳過透明標識,並直接把投影作爲最後一個參數加入通話。

3

如果您單擊LINQPad中的小lambda按鈕,它會向您顯示您要創建的表達式樹,它位於結果框上方和表達式框下方的三個按鈕列表中。