Linq to SQL оставил внешнее объединение с использованием синтаксиса Lambda и объединение в 2 столбца (составной ключ объединения) - PullRequest
0 голосов
/ 22 мая 2018

Я пытаюсь создать внутреннее соединение в 2 столбца, используя Linq to SQL в качестве лямбда-выражения.Обычный запрос будет выглядеть следующим образом.

SELECT * FROM participants 
LEFT OUTER JOIN prereg_participants ON prereg_participants.barcode = participants.barcode
AND participants.event_id = prereg_participants.event_id
WHERE (participants.event_id = 123)

Мне удается выполнить левое внешнее соединение для одного столбца со следующим кодом.

var dnrs = context.participants.GroupJoin(
    context.prereg_participants,
    x => x.barcode,
    y => y.barcode,
    (x, y) => new { deelnr = x, vi = y })
    .SelectMany(
    x => x.vi.DefaultIfEmpty(),
    (x, y) => new { deelnr = x, vi = y })
    .Where(x => x.deelnr.deelnr.event_id == 123)
    .ToList();

Проблема заключается в том, что с приведенным вышеЛямбда Я получаю слишком много результатов, потому что отсутствует часть AND participants.event_id = prereg_participants.event_id.Но что бы я ни пытался, я не получаю правильное количество участников.

Я посмотрел на следующие существующие вопросы, но ни один не решил мою проблему в написании правильной лямбды.И большинство решений - nog в лямбда-формате или не левое внешнее объединение на нескольких столбцах.

Как выполнять объединения в LINQ для нескольких полей в одном объединении

LINQ to SQL - левое внешнее соединение с несколькими условиями соединения

Группировка Используя более двух столбцов по лямбда-выражению

И большинство из них из этого поиска Google

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Мне удалось получить LEFT OUTER JOIN для пары составного внешнего ключа barcode, event_id, работающей как в Linq2Sql, так и в Entity Framework, преобразовав в лямбда-синтаксис в соответствии с этим примером синтаксиса запроса .

Это работает путем создания анонимной проекции, которая используется в соответствии левой и правой сторонам условия соединения:

var dnrs = context.participants.GroupJoin(
    context.prereg_participants,
    x => new { JoinCol1 = x.barcode, JoinCol2 = x.event_id }, // Left table join key
    y => new { JoinCol1 = y.barcode, JoinCol2 = y.event_id }, // Right table join key
    ...

Примечания

ЭтоПодход основан на автоматическом равенстве , присваиваемом идентичным анонимным классам, а именно:

Поскольку методы Equals и GetHashCode для анонимных типов определены в терминах методов Equals и GetHashCode длясвойства, два экземпляра одного и того же анонимного типа равны, только если все их свойства равны.

Таким образом, для двух проекций ключи объединения должны быть одного типа, чтобы быть equal компилятор должен видеть их как один и тот же анонимный класс за кулисами, то есть:

  • Количество соединенных столбцов должно быть одинаковымв обеих анонимных проекциях
  • Типы полей должны быть совместимы одного типа
  • Если имена полей различаются, вам нужно их псевдоним (я использовал JoinColx)

Я поместил пример приложения на GitHub здесь .

К сожалению, пока нет поддержки кортежей значений в деревьях выражений ,поэтому вам нужно придерживаться анонимных типов в проекциях.

0 голосов
/ 22 мая 2018

Вы можете сделать это, используя анонимные типы.

Пример:

var result = from a in context.participants
             join b context.prereg_participants on new { X = a.barcode, Y = a.event_id } equals new { X = b.barcode, Y = b.event_id } into A
             from b in A.DefaultIfEmpty()
             where a.event_id = 123
...