2009-09-21 34 views
5

親子テーブルの関係があります。下の例では、Fooには親レコードを指すFooIDとnull可能なParentFooIDがあります。LINQの条件付き結合

バーテーブルは常に親レコードにリンクされています。これは結果を得るために使用する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) 

乾杯、

ダニエル

答えて

5

あなたの具体的な例としては、CASEを使用しています。本当にCOALESCEあるnull以外の値に戻って落下した場合には、これは動作します:に変換

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] 

キーが左外側JOIですnはCOALESCE(case1, case2)にあるので、式コンバーターはそれを理解しているようです。

0

いくつかの複雑なシナリオがよくLINQでマッピングされていません。私はcaseへの参加が彼らの1つであることを示唆しています。クロスジョイントとしてやり直して...プロファイルしておいて? (すなわち、複雑なjoin(TSQL対以降のSQLfrom from ... from ...(LINQ))?多くの場合、プロファイラは、古いスタイルのアプローチから)同じ(または類似したクエリプランを取得することができます。

+1

私はシナリオからのプロファイリングを行っています。はい、それはインデックススキャンを行います(シークではありません)ので、元のクエリよりも悪化しますインデックスシーク。 – Spruce

+0

少なくとも、価値のあるテスト。 –

1

が直接あなたの質問に答えていないが、元のクエリがよりよい言葉で表現する場合のない条件としてではないでしょう。その場合

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の式は容易にすべきですか?