2017-09-22 13 views
-4

私は、オブジェクトへのLINQは、結合されたデータの異なる実行のための素晴らしい方法だと思った。現実には、それは物事を行うには悪い道を付属しています...ここでオブジェクトにLinq - boondoggle?

は、それに対応しa,b,c,dで、数、数百、3Kと3.5K記録

IEnumerable<MyModel> data = 
    (from a in AList 
    from b in BList.Where(r => r.AId == a.Id) 
    from c in CList.Where(r => r.BId == b.Id) 
    from d in DList.Where(r => r.SomeId == myId && r.Some2Id == c.Some2Id) 
// . . . . . . 

はLINQないし持つ、私たちが持っていたものですそれをすることについて偉大になるはずですか?実際に 、次は

var dTemp = DList.Where(r => r.SomeId == myId).ToList(); 
var cTemp = CList.Where(c => dTemp.Any(d => d.Some2Id == c.Some2Id)).ToList(); 

IEnumerable<MyModel> data = 
    (from a in AList 
    from b in BList.Where(r => r.AId == a.Id) 
    from c in cTemp.Where(r => r.BId == b.Id) 
// . . . . . . 

実際には60倍の速さ、はるかに高速に動作します。そして、私はthis article

Q出くわし:単一LINQを放棄せずに、このクエリを改善する方法はありますか?

これは、パフォーマンスが低下している場合、結合形式のオブジェクトに対するLINQを回避し、いくつかの順次呼び出しで置き換える必要があることを意味しますか?

+2

は 'A'、 'B'、および 'C'に参加します。 'where'の代わりに[' Join'](https://docs.microsoft.com/en-gb/dotnet/api/system.linq.enumerable.join?view=netframework-4.7)関数を使ってみましたか? ? – Reddog

+1

LINQをあまり積極的にペシマイズすることを検討してください。 "私は間違いがないので、フレームワークを壊す必要があります"というのは通常、始めるのに最適な場所ではありません。 –

+0

@EdPlunkettください。私はそれが壊れているとは言いません。しかし、オプティマイザが必要なので、それはあまり仕事をしていないようです。 –

答えて

3

違いを分析しましょう。

まずクエリ:あなたはすべての遅延実行の方法で、DListに、BListCListと二つのフィルタにフィルタをフィルタを実行しています。次に、一種の結合を使用します。
2番目のクエリ:あなたはDList上の静的フィルタを実行し、それを評価し、DListに基づいてCList上の別の静的フィルタと、それを評価して、AListBListの両方に係る繰延-実行フィルタ。ため、2番目のクエリが高速である

  • DListが(原因以前のフィルタに)役に立たない値のために
  • CListを見ていないだけで、以前のフィルタによる有用な値

が含まれていますとにかく、両方のクエリが間違っています。 fromは、基本的にcross-join,as explained hereです。 @Reddogがコメントしたよう、最善の方法は、実際にJoinを使用することです:あなたは、内側にしようとしているように見えます

var data = from a in AList 
      join b in BList on a.Id equals b.AId 
      join c in CList on b.Id equals c.BId 
      join d in DList on c.Some2Id equals d.Some2Id 
      where d.SomeId == someId; 
+0

あなたは正しいです。 'from-from'は' from-join'と同じように動作します。小さなデータセットでは問題は一度も発生しませんでした。しかし、この一人のクライアントにはユニークなセットアップがありました。このセットアップでは、「c」と「d」に大きな[巨大な]セットがあり、あまりうまくやっていませんでした。それでも、それは-140ミリ秒という悪いことではありませんでしたが、そのセットアップの下で繰り返し実行されました。だから140x20 ...今は2msです。 2x20 - 非常に異なる結果。以前はそれを調整していましたが、キャッシュされたデータが置き換えられ、うまくやっているSQL呼び出しに対してベンチマークを行いました。だから、誰も小さなLINQの事実に注意を払わなかった。ありがとうございました –

関連する問題