2016-10-10 2 views
3

Ich habe eine Tabelle mit ungefähr 100.000 Zeilen (und sie wird viel größer werden).OutOfMemoryException beim Iterieren eines großen Datasets

Mein Code wirft jetzt eine OutOfMemoryException, wenn ich um die 80.000 Datensätze in meiner Schleife aufstehen (obwohl mein System über 10GB frei zu der Zeit hat, sieht es so aus, als Visual Studio auf etwa 1,5 GB beschränkt ist).

Der Code soll alle Datensätze durchlaufen und nur nach bestimmten Bedingungen suchen. Ich nahm meinen Code heraus, der den Datensatz tatsächlich verarbeitet, und der Speicher füllt sich immer noch.

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

    } 

} 

Ich dachte, es könnte unter Beibehaltung der Kontext offen, so Refactoring ich den Code zu tun, gerade zu einer Zeit 1000 Datensätze zu nehmen und zuerst um sie alle zu einer Liste aufzählen. Das ist, was ich kam mit:

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

    } 
} 

Das funktioniert viel langsamer, aber füllt noch die Erinnerung bis auf etwa die gleiche Rate von Datensätzen durchgeschleift.

Wie ich meine aktuelle Methode auskommentiert, die alles tut, müssen nur diese toMatch Listen im Speicher bleiben.

Ich bin hier ratlos, kann jemand etwas Licht darauf werfen, wie ich die Erinnerung verwalten sollte?

+0

Können Sie Ihre Übereinstimmungsbedingung in wo Bedingung konvertieren? Etwas wie db.Companies.Where (CheckMatchConditions) .. Möchten Sie auch Objekte irgendwie verarbeiten? Wenn das so ist, wie ? – DolphinSX

Antwort

3

Hinzufügen. AsNoTracking() stellt sicher, dass der DbContext die Entitäten nicht verfolgt.

+1

Perfekt! Speicher geht jetzt nicht über 60mb – Guerrilla

0

Führen Sie keine Iteration durch die Objektauflistung durch, da das EF-Tracking sich ändert, seit Sie Entität in ein Objekt auswählen. Iterieren durch ein DTO.

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

Aber es ist wirklich besser, nicht durch Ihre gesamte Datensammlung zu durchlaufen. Versuchen Sie einfach, Ihre Prüfbedingung in LINQ zu schreiben, damit SQL Server filtern kann.

Verwandte Themen