2016-10-10 128 views
3

我有一個大約100,000行的表(它將變得更大)。OutOfMemoryException當迭代大型數據集

當我在我的循環中獲得大約80,000條記錄時(即使我的系統當時有10GB以上的空閒空間,它看起來像visual studio被限制在1.5GB左右),我的代碼現在會拋出OutOfMemoryException

該代碼旨在遍歷所有記錄並僅檢查特定條件。我拿出實際處理記錄的代碼,並且內存仍然填滿。

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() + "   "); 

    } 

} 

我想這可能是與保持上下文開放,使我重構代碼只取1000條記錄的時間和第一他們全部列舉的清單做。這是我想出了:

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

Add。 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}); 

但是最好不要遍歷整個數據集合。只要嘗試在LINQ中編寫檢查條件方法以允許SQL Server進行篩選。