2011-10-05 4 views
61

Я пытаюсь реализовать запрос в LINQ, который использует левое внешнее соединение с несколькими условиями в предложении ON.LINQ Присоединиться к нескольким условиям в разделе On

Я буду использовать пример из следующих двух таблиц Project (ProjectID, ProjectName) и Задача (TaskID, ProjectID, TASKNAME, Завершена). Я хочу видеть полный список всех проектов с их соответствующими задачами, но только те задачи, которые были завершены.

Я не могу использовать фильтр для Completed == true, потому что это будет отфильтровывать любые проекты, у которых нет заданий. Вместо этого я хочу добавить Completed == true в предложение ON соединения, чтобы был показан полный список проектов, но будут показаны только завершенные задания. Проекты без завершенных задач покажут одну строку с нулевым значением для задачи.

Вот основа запроса.

from t1 in Projects 
join t2 in Tasks 
on new { t1.ProjectID} equals new { t2.ProjectID } into j1 
from j2 in j1.DefaultIfEmpty() 
select new { t1.ProjectName, t2.TaskName } 

Как добавить && t2.Completed == true в оговорку о включении?

Я не могу найти какую-либо документацию LINQ о том, как это сделать.

ответ

82

Вам просто нужно назвать анонимной свойство одинаково с обеих сторон

on new { t1.ProjectID, SecondProperty = true } equals 
    new { t2.ProjectID, SecondProperty = t2.Completed } into j1 

Основываясь на комментариях @svick, вот еще одна реализация, которая может иметь больше смысла:

from t1 in Projects 
from t2 in Tasks.Where(x => t1.ProjectID == x.ProjectID && x.Completed == true) 
       .DefaultIfEmpty() 
select new { t1.ProjectName, t2.TaskName } 
+0

Это кажется, не очевидный способ сделать это. Я не уверен, что пойму, что он должен делать. – svick

+1

@svick - Использование анонимных типов позволяет вам присоединиться к нескольким критериям. Вам просто нужно убедиться, что имена свойств совпадают для обоих типов. Не знаете, откуда возникла путаница? – Aducci

+0

Путаница в том, что на самом деле это имеет смысл, поскольку два равенства связаны «и», а не одно равенство какого-то «странного» объекта. И чтобы доказать свою точку зрения, ваш код ошибочен. Для этого вы должны иметь «истину» с левой стороны и «t2.Complete» справа. – svick

2

Вы не может этого сделать. Предложение join (и метод расширения Join()) поддерживает только equijoins. Это также причина, почему она использует equals, а не ==. И даже если бы вы могли сделать что-то подобное, это не сработало бы, потому что join - это внутреннее соединение, а не внешнее соединение.

20

Здесь вы идете с:

from b in _dbContext.Burden 
join bl in _dbContext.BurdenLookups on 
new { Organization_Type = b.Organization_Type_ID, Cost_Type = b.Cost_Type_ID } equals 
new { Organization_Type = bl.Organization_Type_ID, Cost_Type = bl.Cost_Type_ID } 
Смежные вопросы