2013-04-26 12 views
5

LINQ to SQLの結果を厳密に型指定されたクラス、つまり親と子に投影します。これらの2つのクエリ間の性能差が大きい:1対多投影LINQクエリが繰り返し実行される

スロークエリ - のDataContextからログインするには、各親のためのDBへの別のコールが行われていることを示して

var q = from p in parenttable 
     select new Parent() 
     { 
      id = p.id, 
      Children = (from c in childtable 
         where c.parentid = p.id 
         select c).ToList() 
     } 
return q.ToList() //SLOW 

高速クエリ - DataContextのショーからログイン必要なすべてのデータを返す単一のDBヒットクエリ

var q = from p in parenttable 
     select new Parent() 
     { 
      id = p.id, 
      Children = from c in childtable 
         where c.parentid = p.id 
         select c 
     } 
return q.ToList() //FAST 

私は第二の例の単一問合せスタイルを使用してLINQを強制したいのですが、自分の子供を持つ親クラスを読み込むには、オブジェクトを直接。それ以外の場合、ChildプロパティはIQuerierable<Child>で、Childオブジェクトを公開するために照会する必要があります。

参照された質問が私の状況に対処していないようです。 db.LoadOptionsを使用しても機能しません。おそらく型はDataContextに登録されたTEntityである必要があります。

DataLoadOptions options = new DataLoadOptions(); 
    options.LoadWith<Parent>(p => p.Children); 
    db.LoadOptions = options; 

注意:親子は、Table<TEntity>ではなく、単純なタイプです。親と子の間に文脈上の関係はありません。サブクエリはアドホックです。

問題の要点:2番目のLINQの例ではIQueriableステートメントを実装し、ToList()関数を呼び出さず、何らかの理由でLINQは必要なすべてのデータを取得できる1つのクエリを生成する方法を知っています。最初のクエリで達成されたように、実際のデータをアドホックプロジェクションにどのように埋め込むのですか?また、もし私の質問に誰かが助けてくれたら、私はそれを感謝します。

+0

「子」はどのように「シンプルタイプ」になりますか?マップされた型である必要があります。そして 'parenttable'は' Table'か、前のlinqクエリの結果ですか?いくつかのlinq文によって、L2Sが結合からN + 1に切り替わる可能性があります。 –

+1

マーカーの重複:エンティティフレームワークとlinqとSQLの違いを知っていますか? –

+0

@GertArnold EF/L2SのLINQ部分は、よくこのような質問を機能的に重複していますが、この場合は完全に正しいと信じています。それらは重複していません。再開。 –

答えて

0

データロードに正しいオプションを設定する必要があります。 this

P.S.で

options.LoadWith<Document>(d => d.Metadata); 

ルックLINQToEntityの場合はIncludeのみです。

+0

これは答えが必要なように見えますが、それは私のためには機能しませんでした。私はdlo.Loadと試みた(p => p.Children)。まだ複数のdbヒットを持っています – Paul

+0

@Paul親テーブルを使用する必要はありません。エンティティParentをLINQ2SQLで生成しましたか?コンテキストからParentをリクエストすると、エンティティにはすでにChildrenが含まれています。 –

0

子供が入力されていないため、2番目のクエリは高速です。

子どもが入居しているからといって、最初は遅いです。

あなたのニーズに最も適したものを選択してください。単に機能を一緒に使うことはできません。

EDIT:

@Servy として言う:あなたの2番目のクエリで

あなたが実際に子どもに関するあらゆる情報を取得されていません。あなたはクエリを作成しましたが、それらのクエリの結果を得るためにクエリを実際に実行していません。リストを反復して、各アイテムのChildrenコレクションを反復する場合は、最初のクエリと同じくらいの時間を要します。

1

これを達成するために私が見つけた最も速い方法は、すべての結果を返し、すべての結果をグループ化するクエリを実行することです。 2番目のクエリが多くの呼び出しを行わないように、最初のクエリで.ToList()を実行するようにしてください。

ここでrには、1つのdbクエリで達成したいことがあります。

  var q = from p in parenttable 
        join c in childtable on p.id equals c.parentid 
        select c).ToList(); 
      var r = q.GroupBy(x => x.parentid).Select(x => new { id = x.Key, Children=x }); 
+1

ジョインしてからグループを行うのではなく、単にGroupJoinを使用してください。 – Servy

5

これは、LINQクエリは遅延実行に頼ることを覚えておくことが重要です。 2番目のクエリでは、実際に子どもに関する情報は取得されません。あなたはクエリを作成しましたが、それらのクエリの結果を得るためにクエリを実際に実行していません。リストを反復して、各アイテムのChildrenコレクションを繰り返す場合は、最初のクエリと同じくらい時間がかかります。

クエリも本質的に非常に非効率的です。 Join関係を表すためにネストされたクエリを使用しています。 Joinを代わりに使用すると、クエリープロバイダーとデータベースの両方が適切に最適化され、より迅速に実行されます。また、パフォーマンスを向上させるために、データベースのインデックスを調整する必要があります。ジョインはどのように見えますか?

var q = from p in parenttable 
     join child in childtable 
     on p.id equals child.parentid into children 
     select new Parent() 
     { 
      id = p.id, 
      Children = children.ToList(), 
     } 
return q.ToList() //SLOW 
+0

私は質問がLINQ to SQLについて知っていることを知っていますが、Entity Frameworkを使用している場合、 'ToList()'は 'children'に必須ではありません。 –

関連する問題