2017-07-07 14 views
0

私は複数のテーブルを持っていて、私はを複数参加させて、左にを結びたいと思っています。Linq私はそれを達成するために2つの異なる方法を試しました、そして、彼らの両方が正しい結果を返すようです。Linqによる複数の結合と左結合の方が良い方法はありますか?

ただし、の各メソッドは、異なるSQLクエリを生成します。たとえば、メソッド1は、クエリの最後にいくつかのキーについてもOrder Byを生成します。

私の質問は お勧めですか?なぜ(パフォーマンス& ...)

方法1:

from t1 in Table1 
    // Inner Join on a foreign key in tb1 
    join t2 in Table2 on t1.fkId1 equals t2.Id1 
    // Left Join 
    join t3 in Table3 on t1.fkId1 equals t3.Id1 into ServCons 
    from t3 in ServCons.DefaultIfEmpty() 
    // Left Join 
    join t4 in Table4 on t3.Id2 equals t4.Id2 into t4 
    select new{t1,t2,t3,t4} 

enter image description here

方法2:

from t1 in Table1 
    // Inner Join on a foreign key in tb1 
    from t2 in Table2 .Where(w=>t1.fkId1 == t2.Id1) 
    // Left Join 
    from t3 in Table3 .Where(w=>t1.fkId1 == w.Id1).DefaultIfEmpty() 
    // Left Join 
    from t4 in Table4 .Where(w=>t3.Id2 ==w.Id2).DefaultIfEmpty() 
    select new{t1,t2,t3,t4} 

enter image description here


更新:

私はパフォーマンスがプログラムとプログラマのための重要な課題であることは明らかだと思います。 コストがより安い結果が速くも私の目標です。だから私は約異なるSQLクエリについては、パフォーマンスについての質問と述べたときに十分なのは、2つの方法の間の良い比較は、の賛否両論を書いてそれらの回答を受け入れることになります。

+1

どんな面で? –

+0

私は彼らが同じ結果を返すとは思わない。最初は_inner join_ですが、2番目の_outer_ joinではありませんか?また、生成されたSQLを投稿すると役立ちます。 –

+0

これらは異なるクエリのようです。たとえそれらが同じであっても、あなたのデータに基づいてどちらがより速いかを知ることができます。また、2番目のクエリは混乱しやすいLinqスタイルを混合しています。 – DavidG

答えて

3

まず、SQLの違いは、2つのクエリが同等でないためです。最初のクエリで

join t4 in Table4 on t3.Id2 equals t4.Id2 into t4 

が実際に投影(t4コレクションである)で異なる形状を生成group joinあります。

あなたはleft outer join LINQパターンに変換する場合:

join t4 in Table4 on t3.Id2 equals t4.Id2 into t4Group 
from t4 in t4Group.DefaultIfEmpty() 

生成されたSQLは、(クエリプロバイダにより異なります)1と同じになります。

これでパフォーマンスが向上しました。 LINQには特別なleft outer join演算子がないので、最初はそのような演算子を実装するための "正式に"合意されたLINQパターンです。 Enumerable.Joinの実装では、O(n + m)時間の複雑さを実行するために高速ハッシュベースのルックアップを使用しているため、from ... .Where(...).DefaultIfEmpty()は基本的にO(m * n)で線形検索操作を行うSelectManyです。複雑。

IQueryable<T>の実装では、実際にはクエリプロバイダに依存します。 EF6プロバイダでは、両方の構文が同等で、同じSQLに変換されます。 EF Coreの場合、現在のところ、まだ開発中であり、多くのバグや問題があります。特に、左結合の場合、一般的なアドバイスは難しいです。

IQueryable<T>の実装では、サポートされているかどうか、どのように変換/処理されているか(LINQはその点で壊れています)などのクエリプロバイダ機能を常に確認してください。

一般に、私は最初のパターンを使用すると言います。オブジェクトへのLINQに不可欠であり、うまくいけば、良いクエリプロバイダが認識しているはずです。

しかし、特にEF6の場合、EF6はスマートに認識され、1つの同じSQLに変換されるため、パフォーマンスも同じです。

+1

私はあなたの答えにあなたが提供する詳細が好きです。ありがとうございました。 – RAM

関連する問題