2011-03-09 2 views
4

В основном я делаю запрос типа отчета, где я агрегирую данные из нескольких таблиц и оставляю их присоединенными к одной таблице.Linq to SQL: Левое соединение сгруппированным набором делает Cross Apply/Outer Apply

это выглядит как это:

var docs = from x in DB.Docs 
      group x by x.PersonId into g 
      select new { 
       g.Key, 
       totalSent = g.Sum(x => x.SentDate.HasValue ? 1 : 0), 
       lastSent = g.Max(x => x.SentDate) 
       ... 
      }; 

var summary = from x in DB.People 
       from y in docs.Where(y => y.Key == x.Id).DefaultIfEmpty() 
       select new { 
        x.Id, 
        x.Name, 
        y.totalSent, 
        y.lastSent 
       } 

я ожидал бы, что это создало SQL, который оставил присоединился к DB.People результатам docs, но вместо этого я получаю некоторые сумасшедшие CROSS APPLY((SELECT NULL AS [EMPTY]) as [t1] OUTER APPLY ... вещи.

Я пробовал каждый вариант синтаксиса левого соединения, о котором я могу думать, я даже обернул docs в другом запросе, и я получаю то же самое.

Что мне не хватает?

+0

Вы не получаете результаты, которые вы хотите? «CROSS APPLY» может показаться сумасшедшим, но по моему опыту LINQ to SQL часто умнее, чем я с SQL, и я просто позволяю ему делать это ... если результаты верны. – shaunmartin

+1

Результаты никогда не возвращаются ... 'OUTER APPLY' в основном заставляет меня по группам задавать функцию таблицы для каждой строки' DB.People'. Запрос истекает. –

ответ

0
from x in DB.People 
from y in docs.Where(y => y.Key == x.Id).DefaultIfEmpty() 

Вышеупомянутые данные, очевидно, приведут к декартовым результатам, которые затем фильтруются.

Возможно, вы имели в виду, чтобы присоединиться:

from x in DB.People 
join y2 in docs on x.Id equals y2.Key into g 
from y in g.DefaultIfEmpty() 

Как об этом:

from x in DB.People 
let g = x.Docs 
select new 
{ 
    x.Id, 
    x.Name, 
    totalSent = g.Sum(y => y.SentDate.HasValue ? 1 : 0), 
    lastSent = g.Max(y => y.SentDate) 
} 
+0

Моя версия является ярлыком, если 'docs' не представляет сгруппированный набор, это создало бы левое соединение. –

+0

Итак, вы получаете тот же sql с моим подходом? –

+0

Да, оба подхода дают вам тот же sql. Второй пример не будет работать, к сожалению, поскольку это объекты POCO, построенные поверх некоторой громоздкой архитектуры базы данных с прямым сопоставлением L2S, что у меня нет времени для изменения. Например, документы представляют собой довольно интересный запрос против трех таблиц. –

Смежные вопросы