最近、エンティティ モデルを、4.1 を使用する ObjectContext から 5.0 を使用する DbContext に移動しました。DbContextとObjectContextを使用したクエリのパフォーマンスが非常に悪いことに気付いたので、それを後悔し始めています。テストシナリオは次のとおりです。
どちらのコンテキストも、約 600 のテーブルを持つ同じデータベースを使用します。LazyLoading と ProxyCreation は両方ともオフになっています (コード例には示されていません)。どちらも事前に生成されたビューを持っています。
このテストでは、最初に 1 つの呼び出しを行い、メタデータ ワークスペースを読み込みます。次に、100 回実行される for ループで、コンテキストを新たに作成し、最初の 10 回を受け取る呼び出しを 1 回行います (これは、WCF サービスで使用されることをシミュレートするため、for ループ内でコンテキストを作成します。毎回コンテキスト)
for (int i = 0; i < 100; i++)
{
using (MyEntities db = new MyEntities())
{
var a = db.MyObject.Take(10).ToList();
}
}
これを ObjectContext で実行すると、約 4.5 秒かかります。DbContext を使用して実行すると、約 17 秒かかります。RedGate のパフォーマンス プロファイラーを使用して、これをプロファイリングしました。DbContext の場合、主な原因は UpdateEntitySetMappings というメソッドにあるようです。これはすべてのクエリで呼び出され、メタデータ ワークスペースを取得し、OSpace 内のすべてのアイテムを循環するように見えます。AsNoTracking は役に立ちませんでした。
編集: より詳細に説明すると、問題は実際のクエリではなく、DbSet と ObjectSet の作成\初期化に関係しています。ObjectContext で呼び出しを行うと、ObjectSet の作成に平均 42 ミリ秒かかります。DbContext で呼び出しを行うと、内部 dbset の作成に約 140 ミリ秒かかります。ObjectSet と DbSet の両方が、メタデータ ワークスペースからいくつかのエンティティ セット マッピング ルックアップを行います。私が気付いたのは、DbSet はワークスペース内のすべての型に対してそれを行うのに対し、ObjectSet はそうではないということです。テーブルの数が少ないモデルの方がパフォーマンスの差が少ないと思います (試したことはありません)。