2016-09-09 35 views
1

できるだけ単純化しました。これは、約3,000,000行のテーブルからの読み取りです。私は、データのいくつかの連結されたフィールドから辞書を作成したいと思います。ここで C#エンティティフレームワーク6:メモリが不足しているときに、メモリ不足になる可能性があります。

が私の意見では、これまでにメモリ不足の例外をスローすることはありません、コードです:

public int StupidFunction() 
{ 
    var context = GetContext(); 
    int skip = 0; 
    int take = 100000; 
    var batch = context.VarsHG19.OrderBy(v => v.Id).Skip(skip).Take(take); 
    while (batch.Any()) 
    { 
     batch.ToList(); 
     skip += take; 
     batch = context.VarsHG19.OrderBy(v => v.Id).Skip(skip).Take(take); 
    } 

    return 1; 
} 

を私の意見では、バッチオブジェクトは、単純に割り当てられた各反復と前のメモリを交換する必要があります前のバッチオブジェクトはガベージコレクションされる必要があります。私は、この関数のループは、ほぼ静的な量のメモリを取る必要があります。最悪の場合、1行×10万のメモリが必要です。このテーブルの行の最大サイズは540バイトです。私はedmxからNavigation Propertiesを削除しました。

+2

Entity Frameworkコンテキストは、データベースから読み取ったすべてのエンティティを追跡し、変更を追跡します。反復間のコンテキストを再作成してみてください。 – MarcinJuraszek

+2

'AsNoTracking'を使ってトラッキングをオフにすることができます。フィルタリングされたIEnumerable のDbSet からforeachループを使用するのはなぜですか? 'Select ()' – Igor

+0

Thanks Igorを使用して、匿名タイプを使用して必要なものだけを返すことによっても助けることができます。それは今、完璧な意味があります。実際のコード(これは問題を特定するためのWTFコードです)では、返されたIQueryableをforeachで繰り返し、辞書に値を追加しています。実際のコードでは、ToList()は呼び出されません。私は、結果セットのToList()ではなく、コンテキスト内の変更トラッキングによって例外がスローされていることを認識していませんでした。 – urbadave

答えて

2

AsNoTrackingを使用してトラッキングをオフにすることができます。なぜフィルタリングされたIEnumerableのDbSetからforeachループを使用しないのですか?また、Select() - Igorを使用して匿名タイプを使用して必要なものだけを返すことによっても助けてもらうことができます。Igor

ありがとうございました。

public int StupidFunction() 
{ 
    var context = GetContext(); 
    int skip = 0; 
    int take = 100000; 
    var batch = context.VarsHG19.AsNoTracking().OrderBy(v => v.Id).Skip(skip).Take(take); 
    while (batch.Any()) 
    { 
     batch.ToList(); 
     skip += take; 
     batch = context.VarsHG19.AsNoTracking().OrderBy(v => v.Id).Skip(skip).Take(take); 
    } 

    return 1; 
} 

No Out of Memory Exception。

+0

良い取引、あなたの問題を解決してうれしいです。 – Igor

0

あなたは何かにクエリの結果を割り当てていません。新しいメモリを割り当てるために何をすべきかをC#が理解する方法。

バッチはクエリであり、何も含まれません。 .ToList()を呼び出すと、クエリが実行され、レコードが返されます。

public int StupidFunction() 
{ 
    var context = GetContext(); 
    int skip = 0; 
    int take = 100000; 
    var batch = context.VarsHG19.OrderBy(v => v.Id).Skip(skip).Take(take).ToList(); 
    while (batch.Any()) 
    { 

     skip += take; 
     batch = context.VarsHG19.OrderBy(v => v.Id).Skip(skip).Take(take).ToList(); 
    } 

    return 1; 
}