2016-10-10 17 views
3

私は約100,000行のテーブルを持っています(それはもっと大きくなるでしょう)。大きなデータセットを反復するときにOutOfMemoryExceptionが発生する

私のループでは80,000レコードに達した時点でコードがOutOfMemoryExceptionになっています(私のシステムは10GB以上の空きがありますが、ビジュアルスタジオは約1.5GBに制限されています)。

このコードは、すべてのレコードをループして特定の条件をチェックすることを目的としています。私は実際にレコードを処理し、メモリはまだいっぱい私のコードを取り出した。

using (var db = new PlaceDBContext()) 
{ 
    Messages.Output("Total: " + db.Companies.Count()); 
    int count = 0; 
    foreach (var company in db.Companies) 
    { 

     // I am not actually doing anything here, 
     // I took out my code and the memory still fills up 
     // CheckMatchConditions(company); 

     count++; 

     Console.SetCursorPosition(0, Console.CursorTop); 
     Console.Write(count.ToString() + "   "); 

    } 

} 

私はそれはので、私はただ一度に1,000レコードを取り、最初のリストにそれらすべてを列挙するためにコードをリファクタリングオープンコンテキストを維持したまま行うことかもしれないと思いました。これは私が思いついたものです:

int count = 0; 
int total = 0; 
using (var db = new PlaceDBContext()) 
{ 
    Messages.Output("Total: " + db.Companies.Count()); 
    total = db.Companies.Count(); 
} 
while (count < total) 
{ 
    List<Company> toMatch = new List<Company>(); 
    using (var db = new PlaceDBContext()) 
    { 
     toMatch = db.Companies.Include(x => x.CompaniesHouseRecords).OrderBy(x => x.ID).Skip(count).Take(1000).ToList(); 
    } 

    foreach (var company in toMatch) 
    { 

     // CheckMatchConditions(company); 

     count++; 

     Console.SetCursorPosition(0, Console.CursorTop); 
     Console.Write(count.ToString() + "   "); 

    } 
} 

これは非常に遅く動作しますが、ループされたレコードとほぼ同じ速度でメモリをいっぱいにします。

何かをする私の実際の方法をコメントしたので、これはちょうどtoMatchのリストがメモリに残っている必要があります。

私はここで紛失しています。誰かがメモリをどのように管理すべきかについてのいくつかの光を当てはめることができますか?

+0

条件を一致条件に変換できますか?何かdb.Companies.Where(CheckMatchConditions)..のようにオブジェクトを何とか処理したいのですか?もしそうなら、どうですか? – DolphinSX

答えて

3

追加。 AsNoTracking()は、DbContextがエンティティを追跡しないことを保証します。

using (var db = new PlaceDBContext()) 
{ 
    Messages.Output("Total: " + db.Companies.Count()); 
    int count = 0; 
    foreach (var company in db.Companies.AsNoTracking()) 
    { 
     count++; 
     Console.SetCursorPosition(0, Console.CursorTop); 
     Console.Write(count.ToString() + ". company : " + company.someProp); 
    } 
} 
+1

パーフェクト!メモリが60MB以上にならない – Guerrilla

0

エンティティをオブジェクトに選択してからEFの追跡が変化するため、オブジェクトコレクションを反復処理しないでください。 DTOを繰り返します。

db.Companies.Select(c => new CompanyDto{ Name = c.Name}); 

ただし、データコレクション全体を繰り返し処理しない方が良いです。 SQL Serverがフィルタリングを実行できるようにするには、LINQにチェック条件メソッドを記述してみてください。

関連する問題