1

EF4.1 の使用中にメモリの問題が発生しました。問題は主に次の状況で発生します。1 つ以上のコースに参加できる学生がいて、複数のユーザーが同じコースに参加できるとします。だから、私は次のようなものを持っています:

Student * < - > 1-* Course

BD に 2 人の生徒と 1 つのコースがあるとします。このような:

Ana は英語コースに参加します Bob は英語コースに参加します

私のオブジェクトグラフは次のようなものです:

Ana  
    \
      English Course
    /
Bob

これで問題ありません。

これを保存すると、student テーブルに 2 行、courses テーブルに 1 行が保存されます。

問題は、このデータを取得しようとするときです。

次のようなことをすると:

 var students = (from s in students
                 select s).Include("Courses");

これは結果のグラフです:

 Ana -> English Course
 Bob -> English Course

オブジェクトが複製されます。このツリーの深さがはるかに大きく、何千人もの学生と何千ものコースがあり、同じコースに何百人もの学生が参加している状況を想像してみてください。

このクエリのメモリ使用量は非常に大きくなります。この参照の問題を解決するにはどうすればよいですか?

4

2 に答える 2

0

クエリでを使用するAsNoTrackingと、オブジェクトはコンテキストに読み込まれず、そこにキャッシュされません。しかし、コンテキストがなければ ID マッピングはありません。つまり、キー プロパティ値とオブジェクト参照 ID の間に一意のマッピングがありません。その結果、EF は読み込まれたナビゲーション プロパティごとに新しいオブジェクトを作成するため、同じキーに対して複数のオブジェクトを取得します。これにより、ID マップを作成する必要がなく、変更追跡用のプロパティ スナップショットも必要ないため、読み込みが速くなりますが、より多くのメモリを消費する可能性があります。

私の知る限り、データをコンテキストにロードしない限り、オブジェクトの実体化中にオブジェクトの重複を避ける方法はありません。

データを ロードする際のパフォーマンスを向上させるためにAsNoTracking、コース コレクションの熱心なロードから明示的なロードへの移行を試みることができます。一括読み込みは、データベースとクライアント間で転送されるデータの膨大な増加につながることが知られており、パフォーマンスに非常に悪影響を及ぼす可能性があります。コードを明示的にロードすると、次のようになります。

// no Include and no AsNoTracking here
var students = (from s in context.Students select s).ToList();
foreach (var student in students)
{
    context.Entry(student).Collection(s => s.Courses).Load();
}

これにより、ロードごとに 1 つの追加のデータベース クエリが作成さstudentれ、Coursesコレクションがロードされます。パフォーマンスに関しては、これを行うのはクレイジーに聞こえますが、熱心な読み込みを使用した単一のクエリよりもはるかに高速になる例があります (この例が示すように:同じ子を持つエンティティを検出します (この回答へのコメントを参照してください: 167 からのパフォーマンスの向上)熱心な読み込みから明示的な読み込みに移行した後、1 秒から 3.4 秒に短縮されます))。

オブジェクトはコンテキストに具体化されるため、ここで複製しないでください。

于 2011-11-02T15:40:59.790 に答える