Как создать объединение в дереве выражений для LINQ? - PullRequest
1 голос
/ 28 января 2009

У меня есть объект Task, у которого есть коллекция объектов Label ... в базе данных таблицы называются Task и Label.

Существует множество способов поиска Задачи, поэтому с помощью 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

Есть ли способ сделать это с помощью дерева выражений? Я застрял! Любая помощь будет принята с благодарностью!

Ответы [ 3 ]

5 голосов
/ 28 января 2009

Предложение "join" (а не "join ... into") в выражении запроса переводится в вызов Join. Сложный бит - прозрачные идентификаторы - из соединения выходит только одна последовательность, и в нем должны быть и t, и l (в вашем примере), так что компилятор совершает магию.

У меня не так много времени, чтобы вдаваться в детали, но, вероятно, лучше просто показать вам, как переводится выражение вашего запроса.

Это:

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, и l из исходного выражения.

РЕДАКТИРОВАТЬ: ответ Дэвида Мортона дает более эффективный способ сделать это. Его строка эквивалентна:

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

Если у вас есть только предложение select после объединения, компилятор может пропустить прозрачный идентификатор и поместить проекцию непосредственно как последний параметр в вызове Join.

4 голосов
/ 28 января 2009

Я считаю, что это должно сделать это:

Tasks.Join(Labels.Where(l => l.Name == "accounting"), t => t.TaskId, l => l.SourceId, (t, l) => t)
3 голосов
/ 28 января 2009

Если вы нажмете маленькую лямбда-кнопку в LINQPad, она покажет вам дерево выражений, которое вы пытаетесь создать, оно находится в списке из трех кнопок над полем результатов и под полем выражений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...