лямбда-выражение - эквивалент sql внешнего соединения - PullRequest
1 голос
/ 16 августа 2010

Мне нужно написать метод на C #, который будет возвращать какой-то конкретный словарь из БД. Допустим, данные, хранящиеся в 2 таблицах, выглядят так:

Таблица групп (id, name):

1, 'Management'  
2, 'IT Department'  
3, 'Production'  

Пользователи (id, name, groupId, projectId):

1, 'John', 1, 1  
2, 'Ben',  2, 1  

Теперь мне нужно проверить, что в каждом проекте в каждой группе есть не менее одного пользователя. Запрос sql для получения этой информации будет:

declare @projectId int;  
set @projectId = 1;  

select g.Name, case when(isnull(u.id,0) > 0) then 1 else 0 end HasUsers  
from groups g  
left join users u  
on g.id = u.groupId and u.projectId = @projectId;  

Информация, возвращаемая из этого запроса, выглядит следующим образом:

'Management',    1  
'IT Department', 1  
'Production',    0  

Что такого особенного в запросе? Условие для projectId включено в часть 'join', а не в часть 'where'. В результате строка для группы «Производство» возвращается со значением 0. Когда мы перемещаем условие для projectId в «где часть», запись не будет присутствовать в возвращаемом результате.

Наконец, вопрос - возможно ли достичь подобного эффекта, используя одно лямбда-выражение? (Я знаю, что могу получить 2 коллекции и, используя какое-то утверждение цикла, получить конечный результат, но это не предмет этого вопроса)

С уважением,
яки

Ответы [ 3 ]

3 голосов
/ 17 августа 2010

Хорошо, я думаю, что я понял это сам. Созданный sql немного сложнее, чем в оригинальном сообщении, но результат такой же.

var query = db
  .Groups
  .GroupJoin(db.Users.Where(u => u.projectId == 1) , g => g.Id, u => u.groupId, (g, u) => new { u, g })
  .SelectMany(x => x.u.DefaultIfEmpty(), (g,u) => new {Group = g.g, Users = u})
  .Select(res => new {Group = res.Group.Name, Counter = (res.Users != null)});
0 голосов
/ 16 августа 2010

Полу снимок в темноте:

from g in groups 
join u in users on  
new { a = g.id, b=u.projectid } equals new { a = u.groupid, b = [var_goes_here] } into t 
from u in ps.DefaultIfEmpty() 
select new { GroupName = g.name, HasUsers = u == null ? 0 : 1 };
0 голосов
/ 16 августа 2010

Запросы LINQ Outer Join имеют следующий вид:

from x in collection
join y in otherCollection on x.Key equals y.Key into g
from o in g.DefaultIfEmpty()
select new Whatever {
    Something = x,
    Other = o
};

Если нет связанных y для присоединения к x, тогда o, выбранный из g, будет нулевым

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