Entity Framework - Фильтр по включенной таблице, но включает родительские записи без дочерних элементов - PullRequest
0 голосов
/ 21 апреля 2020

Это уже несколько раз спрашивали, но здесь снова. Я пытаюсь использовать отношение 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. который мне не очень повезло конвертировать.

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