2016-07-11 9 views
3

レッツを使用して、私が持っていると言う:チェーンSelectManyの代わりにJOINステートメント

enter image description here

私は特定の学校(IdSchool = 2)に属しているすべてのクラスを見つけなければならないし、例えば科学からであること。とにかく

私は私が使用してLINQは非常にeassy見つけるため:

using(var context = new MyEntities()) 
{ 
    var classesOfInterest = context.Schools 
         .SelectMany(x => x.Teachers) 
         .SelectMany(x => x.Classes) 
         .Where(x => /* custom criteria */) 
         .ToList(); 
} 

だから私の質問は次のとおりです。は、結合文悪い習慣を使用して、このアプローチinstadを使用していますか?代わりにJOIN文を使用する必要がありますか? 5つの「SelectMany」ステートメントをチェーン化するケースがあります。今はデータベースが小さいのですごくうまくいきます。大きなデータベースで作業する場所をこのようなものにすると、私は避けるべきですか?

+2

翻訳されたSQLクエリの実行が 'SelectMany'アプローチではるかに遅くなると思います。私は間違いなく結合を使用します。しかし、私の言葉をそれに服用しないでください。生成されたSQLをログに記録し、実行計画を比較し、自分で参照してください。 – sstan

+0

ありがとう@sstan。結果は非常に似ています。私は大規模なデータベースを試してみる必要があり、あなたが言うように結果を比較する必要があると思います。私がSelectManyを使ってチェーンすることができればいいです。そのようにクエリを作成するのが早いです。 –

+2

これは実際にはEFの推奨アプローチです。 EFは、 "ナビゲーション"プロパティのメタ情報を使用して結合を生成します。 –

答えて

3

このアプローチを使用すると、結合ステートメントの悪い習慣を使用していますか?

全くありません。実際には、EFで作業する場合、が推奨(またはが好ましい)です。いわゆるのナビゲーションプロパティは、EFの美点の1つです。あなたが持っているとき(そしてあなたがそうするとき)、「手動」の結合を使う必要はありません。オブジェクト/コレクションであれば "ナビゲート"し、書き込んだような場合はEFによって結合が生成されますが、一方のテーブルのどのフィールドが他方のフィールドに結合されているかを覚えておく必要はありません。

例えば

、クエリのこの簡易版みましょう:使用

var queryA = context.Schools.SelectMany(x => x.Teachers); 
var sqlA = queryA.ToString(); 

と同等に参加する:

var queryB = from s in context.Schools 
      join t in context.Teachers on s.Id equals t.IdSchoool 
      select t; 
var sqlB = queryB.ToString(); 

あなたはsqlAsqlBは1と同じであることがわかります。

+0

'IQueryable 'の 'SelectMany'が内部結合に変換されていますか?もちろん、オオタビオクク – octavioccl

+0

です。ほかに何か? 'SelectMany'は例えばdb.School内の' from s.Teachers select t'から 'from 'を書くときです。それは「INNER JOIN」に翻訳されています。 's.Teachers.DefaultIfEmpty()'を使うと、 'LEFT OUTER JOIN'が得られます。 –

+0

まあ、私はそれがどこの条件とのクロス結合でもあると思っていました。私が知っている限り、Linqの二重の 'from'が' SelectMany'呼び出しに変換されているので、クロス・ジョインに変換できると思ったのです。 – octavioccl

関連する問題