2

私はEntityFrameworkProfilerを使用してMVCプロジェクトのデータアクセスをテストしてきましたが、N + 1の問題のために、必要以上に多くのデータベースクエリを実行しているページに出くわしました。

これが私の問題を示す簡単な例です:

var club = this.ActiveClub; // ActiveClub uses code similar to context.Clubs.First() 
var members = club.Members.ToList();
return View("MembersWithAddress", members);

ビューはメンバーをループし、各メンバーのナビゲーションプロパティに従って、アドレスも表示します。各アドレス要求により、追加のデータベースクエリが生成されます。

これを解決する1つの方法は、Includeを使用して、必要な追加のテーブルが事前に照会されていることを確認することです。ただし、これは、コンテキストに直接接続されているクラブのObjectSetでのみ実行できるようです。この場合、ActiveClubプロパティは多くのコントローラーで共有されているため、メンバーとアドレステーブルを事前に照会する必要はありません。

次のようなものを使用できるようにしたいと思います。

var members = club.Members.Include("Address").ToList();

ただし、MembersはEntityCollectionであり、Includeメソッドがありません。

メンバーEntityCollectionに強制的にロードし、EFにアドレスもロードするように依頼する方法はありますか?

または、この方法でエンティティのEntityCollectionナビゲーションプロパティを使用していますが、これは非常に悪い考えです。コンテキストから取得するときに、何をロードしているのかを知っておく必要がありますか?

4

1 に答える 1

5

エンティティがから継承する場合は、EntityObjectこれを使用してみてください:

var members = club.Members.CreateSourceQuery()
                          .Include("Address")
                          .ToList();

遅延読み込みプロキシで POCO を使用する場合は、これを使用してみてください。

var members = ((EntityCollection<Club>)club.Members).CreateSourceQuery()
                                                    .Include("Address")
                                                    .ToList();

POCO は EF への依存を削除するために使用されるため、明らかに 2 番目のバージョンはあまり良くありませんが、コレクションを EF クラスに変換する必要があります。もう 1 つの問題は、クエリが 2 回実行されることです。プロパティにアクセスするために遅延読み込みがMembers1 回トリガーされ、次に を呼び出すと 2 番目のクエリが実行されますToList。これは、クエリを実行する前に遅延読み込みをオフにすることで解決できます。

共有されていると言うときActiveClub、派生コントローラーで使用されるベースコントローラーのプロパティのようなものを意味すると思います。このような場合でも、別のコントローラーで別のコードを使用してプロパティを埋めることができます。

于 2011-05-13T22:55:53.243 に答える