Это уже несколько раз спрашивали, но здесь снова. Я пытаюсь использовать отношение left join (дочерние записи могут быть нулевыми) и заставить EF вернуть правильный набор результатов.
Quick Question - Может ли объединение НА критерии должны быть отменены или расширены?
var Projects = _context.Project
.Include(p => ProjectCode)
.On(p.projectId == pc.ProjectId && pc.Active)
Упрощенные таблицы. Проект может иметь 0, 1, n кодов проектов.
Company (CompanyId, Name, ....)
Project (ProjectId, CompanyId, Name, Active, ....)
ProjectCode(ProjectCodeId, ProjectId, Name, Active, .....)
Цель: по заданному CompanyId получить список активных проектов и перечислить коды, если они существуют.
var Projects = _context.Project
.Include(p => ProjectCode)
.Where(p => p.CompanyId == cId && p.Active);
Monkey Wrench - система разрешает мягкое удаление. Таким образом, ProjectCodes могут существовать, но быть неактивными, что должно быть отфильтровано. Приведенный выше запрос включает неактивные коды.
Использование ЛЮБОГО
var Projects = _context.Project
.Include(p => ProjectCode)
.Where(p => p.CompanyId == cId && p.Active && p.ProjectCode.Any(e => e.Active));
Набор результатов теперь только включает проекты с кодами - это не внутреннее объединение, но использование существует чтобы получить аналогичный результат
SELECT ..........
FROM Project AS [p]
LEFT JOIN (
SELECT .....
FROM [ProjectCode] AS [p0]
) AS [t] ON [p].[ProjectId] = [t].[ProjectId]
WHERE ([p].[CompanyId] = @__CompanyId_0 AND @__CompanyId_0 IS NOT NULL) AND EXISTS
(
SELECT 1
FROM [ProjectCode] AS [p1]
WHERE [b].[ProjectCodeId] = [p1].[ProjectCodeId] AND [p1].[Active] = CAST(1 AS bit)
)
Немного поиграв, я получил
var Projects = _context.Project
.Include(p => p.ProjectCode)
.Where(p => p.CompanyId == cId || p.ProjectCode.Any(pc => pc.Active && pc.ProjectId == p.ProjectId))
.Where(p => p.CompanyId == cId && p.Active);
Первый WHERE в основном возвращает все коды для проекта, поэтому его обратно в левое соединение без дети фильтруются. Но в SQL, просто добавив «t.ProjectId IS NULL ИЛИ» до того, как EXISTS вернет правильный набор результатов.
SELECT ..........
FROM Project AS [p]
LEFT JOIN (
SELECT .....
FROM [ProjectCode] AS [p0]
) AS [t] ON [p].[ProjectId] = [t].[ProjectId]
WHERE ([p].[CompanyId] = @__CompanyId_0 AND @__CompanyId_0 IS NOT NULL) AND
( t.ProjectID IS NULL OR
EXISTS
(
SELECT 1
FROM [ProjectCode] AS [p1]
WHERE [b].[ProjectCodeId] = [p1].[ProjectCodeId] AND [p1].[Active] = CAST(1 AS bit)
)
)
За исключением того, что мои результаты поиска показывают, что люди, пытающиеся исключить ноль, не ищут его специально , Это в сочетании с тем, что оно является дочерним свойством, может означать, что это тупик, но я подумал, что я увижу, есть ли у кого предложения.
Я кратко изучил GroupJoin, но в самом запросе есть несколько шагов Include, ThenInclude. который мне не очень повезло конвертировать.