JOIN и LEFT JOIN эквивалент в LINQ - PullRequest
6 голосов
/ 18 июня 2009

Я работаю со следующим запросом SQL:

SELECT 
a.AppointmentId,
a.Status,
a.Type,
a.Title,
b.Days,
d.Description,
e.FormId
FROM Appointment a (nolock)
LEFT JOIN AppointmentFormula b (nolock)
ON a.AppointmentId = b.AppointmentId and b.RowStatus = 1
JOIN Type d (nolock)
ON a.Type = d.TypeId
LEFT JOIN AppointmentForm e (nolock)
ON e.AppointmentId = a.AppointmentId
WHERE a.RowStatus = 1
AND a.Type = 1
ORDER BY a.Type

Я не уверен, как добиться соединения в LINQ. Все мои таблицы имеют отношения внешнего ключа.

Ответы [ 3 ]

29 голосов
/ 19 июня 2009
SELECT A.X, B.Y
FROM A JOIN B ON A.X = B.Y

Этот вызов метода linq (для соединения) будет генерировать вышеупомянутое соединение.

var query = A.Join
(
  B,
  a => a.x,
  b => b.y,
  (a, b) => new {a.x, b.y} //if you want more columns - add them here.
);

SELECT A.X, B.Y
FROM A LEFT JOIN B ON A.X = B.Y

Эти вызовы методов linq (для GroupJoin, SelectMany, DefaultIfEmpty) приведут к вышеприведенному левому соединению

var query = A.GroupJoin
(
  B,
  a => a.x,
  b => b.y,
  (a, g) => new {a, g}
).SelectMany
(
  z => z.g.DefaultIfEmpty(),
  (z, b) =>
    new  { x = z.a.x, y = b.y } //if you want more columns - add them here.
);

Ключевой концепцией здесь является то, что методы Линка дают результаты иерархической формы, а не сплющенные формы строк-столбцов.

  • Линк GroupBy создает результаты в виде иерархии с ключом группировки, соответствующим коллекции элементов (которые могут быть не пустыми). Предложение SQL GroupBy создает ключ группировки с агрегированными значениями - нет подмножества для работы.
  • Аналогично, GroupJoin Линка создает иерархическую форму - родительскую запись, сопоставленную с коллекцией дочерних записей (которая может быть пустой). * Sql LEFT JOIN создает родительскую запись, соответствующую каждой дочерней записи, или нулевую дочернюю запись, если других совпадений нет. Чтобы получить форму Sql из формы Linq, необходимо распаковать коллекцию дочерних записей с помощью SelectMany - и обработать пустые коллекции дочерних записей с помощью DefaultIfEmpty.

И вот моя попытка связать этот sql в вопросе:

var query =
  from a in Appointment
  where a.RowStatus == 1
  where a.Type == 1
  from b in a.AppointmentFormula.Where(af => af.RowStatus == 1).DefaultIfEmpty()
  from d in a.TypeRecord //a has a type column and is related to a table named type, disambiguate the names
  from e in a.AppointmentForm.DefaultIfEmpty()
  order by a.Type
  select new { a.AppointmentId, a.Status, a.Type, a.Title, b.Days, d.Description, e.Form }
5 голосов
/ 18 июня 2009

Возможно, вам придется слегка подправить это, когда я выходил из манжеты, но есть несколько важных вещей, о которых следует помнить. Если у вас правильно установлены отношения в dbml, вы сможете неявно выполнять внутренние объединения и просто получать доступ к данным через исходную таблицу. Кроме того, левые соединения в LINQ не так просты, как мы можем надеяться, и вам нужно пройти через синтаксис DefaultIfEmpty, чтобы это произошло. Я создал анонимный тип здесь, но вы можете добавить его в класс DTO или что-то в этом роде. Я также не знал, что вы хотели бы сделать в случае нулей, но вы можете использовать ?? синтаксис, чтобы определить значение, чтобы дать переменную, если значение равно нулю. Дайте мне знать, если у вас есть дополнительные вопросы ...

var query = (from a in context.Appointment
join b in context.AppointmentFormula on a.AppointmentId equals b.AppointmentId into temp
from c in temp.DefaultIfEmpty()
join d in context.AppointmentForm on a.AppointmentID equals e.AppointmentID into temp2
from e in temp2.DefaultIfEmpty()
where a.RowStatus == 1 && c.RowStatus == 1 && a.Type == 1
select new {a.AppointmentId, a.Status, a.Type, a.Title, c.Days ?? 0, a.Type.Description, e.FormID ?? 0}).OrderBy(a.Type);
1 голос
/ 09 июня 2010

Если вы хотите сохранить подсказки (NOLOCK), я опубликовал в блоге удобное решение с использованием методов расширения в C #. Обратите внимание, что это то же самое, что добавить подсказки nolock к каждой таблице в запросе.

...