Условные объединения в LINQ - PullRequest
       8

Условные объединения в LINQ

5 голосов
/ 21 сентября 2009

У меня есть отношения родительских и дочерних таблиц. В приведенном ниже примере Foo имеет FooID и обнуляемый ParentFooID, который указывает на родительскую запись.

Таблица Bar всегда связана с родительской записью. Это SQL, который я использую для получения результата.

Select * from Foo f
JOIN  Bar b
  ON b.FooID =  
     CASE 
       WHEN f.ParentFooID is null
         THEN f.FooID
       ELSE f.ParentFooID
     END

У меня возникли проблемы с получением этого запроса LINQ. Я бы хотел избежать перекрестного соединения, например:

    var q = from f in Foo 
            from b in Bar 
            where  b.FooID == (f.ParentFooID ?? f.FooID)

Приветствия

Daniel

Ответы [ 3 ]

5 голосов
/ 21 сентября 2009

Ваш конкретный пример использует CASE для возврата к ненулевому значению, которое на самом деле просто COALESCE. В этом случае это работает:

var q = from f in dc.Foos
        join
        b in dc.Bars
        on
        (f.ParentFooID ?? f.FooID)
        equals
        b.FooID
        into grouped
        select grouped;

Что означает:

SELECT ...
FROM [dbo].[Foo] AS [t0]
LEFT OUTER JOIN [dbo].[Bar] AS [t1]
ON (COALESCE([t0].[ParentFooID],[t0].[FooID])) = [t1].[FooID]
ORDER BY [t0].[FooID], [t1].[BarID]

Ключ - это левое внешнее соединение на COALESCE(case1, case2), поэтому преобразователь выражений, похоже, это понимает.

1 голос
/ 21 сентября 2009

Непосредственно не отвечает на ваш вопрос, но исходный запрос не будет лучше сформулирован без условного кейса:

Select * 
from Foo f
JOIN Bar b ON b.FooID = f.FooID
Where f.ParentFooID is null
UNION ALL
Select * 
from Foo f
JOIN Bar b ON b.FooID = f.ParentFooID
Where f.ParentFooID is not null

В каком случае выражение LINQ должно быть проще?

0 голосов
/ 21 сентября 2009

Некоторые сложные сценарии не очень хорошо отображаются в LINQ; Я хотел бы предположить, что присоединение к case является одним из них. Вы делаете это как кросс-соединение ... ваш профилировал это? (т. е. последующий SQL от from ... from ... (LINQ) против сложного join (TSQL)? Во многих случаях профилировщик может получить тот же (или аналогичный) план запроса из подходов старого стиля.

...