2016-06-20 29 views
0

これは、Entity Framework 7を使用してDBからデータを取得するために使用されるLINQクエリです。.Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First()のペアがあります。このクエリを最適化する方法はありますか?それを行う必要があるのか​​、それともEFがそれを最適化する必要がありますか?EF最適化複合LINQクエリが必要ですか?

var bs = await db.Building.Include(x => x.CollectedMaterial) 
        .Where(x => x.MaterialIDLocked == BuildingDataLockType.LockedByBuildingInfoSource) 
        .Where(x => x.CollectedMaterial.Count > 0) 
        .Where(
         x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats >= firstRepeatsCount) 
        .Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().MaterialID != x.MaterialID) 
        .ToListAsync(); 
+0

すべての答えは、おかげですべての私のために便利です! – AsValeO

答えて

2

AFAIK AFAIKでは、複数のwhere句を使用してリストをフィルタリングするのではなく、単一のwhere句の中に条件を入れてください。

EDIT:ええ、multiple where clauses同様

ヒントを使用して罰金のようだ:多分、不要なデータを取得することにより、メモリ内のオブジェクトにフィルタを適用していないクエリ自体内のすべてのデータをフィルタリングするようにしてください不要なフィールドであっても、必要なフィールドだけを選択するために投影操作を使用することもできます。

答えhereもそう言って、私は通常、パフォーマンスの改善が必要とされるであろうどれだけ評価するために試してみてください/ wの読みやすさとパフォーマンスBのバランスのために行く、またVisual Studio Profilerを試してみてください、それはメモリなど、CPUのサンプリング、

を持っています

getメソッドでそのコードを記述する場合、DbSetでAsNoTrackingメソッドを使用すると、Entity Frameworkはデフォルトで作成する追跡オブジェクトを使用してEntity Frameworkを追跡しないため、パフォーマンスが向上します。

DbContextオブジェクトのDatabase.Logプロパティを使用して、生成されたSQLクエリを記録し、複雑なクエリがどのように見えるかを確認すると、これが役立ちます。

あなたはIQueryableで作業しているので、あなたは限りあなた.Where()条件をチェーンすることができますあなたはcontext.Database.Log = message => Trace.WriteLine(message);

+0

ありがとう、多くの便利なもの。 'IQueryable'(Petrの答え)に対して複数の' .Where() 'がOKであるように見えます。 – AsValeO

+1

ええ、複数の.Where()句を使用するのは大丈夫ですが、コードの可読性を向上させることができます。 –

1

としてデバッグまたはトレースに他のアプリケーションにログインすることができますcontext.Database.Log = Console.WriteLine;

として、コンソールアプリケーションにログインすることができますあなたが作成しているのは、後で評価される式ツリーです。

実際にDBからデータを取得すると(例ToList()のように)、EFは実際の最適化されたSQLクエリを作成します。

あなたができることはDBに対してSQLプロファイラを実行してキャッチし、実際に生成されたのEFクエリを参照することです。

1

AFAIKは、実際のdb呼び出しが実現されるまで、エンティティをすべて最適化します。あなたの場合、それは.ToListAsyncへの呼び出しが行われたときです。

EDIT:thisコメントを見ると、すべてのクエリをマージする必要があります。あなたができるならば、変数defitionを使用することを考える。

最適化について、あなたは

.Where(x => { 
    var firstRepeats = x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats; 
    return (firstRepeats.Repeats >= firstRepeatsCount && 
      firstRepeats.MaterialID != x.MaterialID) }) 

.Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats >= firstRepeatsCount) 
.Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().MaterialID != x.MaterialID) 

をマージすることもできます(未テスト、しかし)

+0

残念ながら、 'IQueryable'で文の本文を使用することはできません"文の本文を持つラムダ式は式ツリーに変換できません "。 – AsValeO

+0

そして、あなたはどこかであなたの演奏を壊すことになる前に、データを抽出してはなりません。 – torendil

関連する問題