Hallo,
habe ein Tool geschrieben zum exportieren von Daten aus einer Datenbank. Dieses funzt auch wunderbar, jedoch sind es über 300 k Datensätze die zu exportieren sind. Nach etwa 130 k bis 150 k Datensätzen sind vom Prog 1,5 GB Arbeitsspeicher zugewiesen und das prog stürzt ab mit einer OutOfMemory Exception.
Die Daten werden über eine DLL aus der Datenbank serialisiert und über den Streamwriter in eine Datei geschrieben. Der Export erfolgt in einer foreach Schleife, in der keine Variablen deklariert werden, nur initalisiert.
Gruss Casiopeia
Hallo,
der Export scheint nicht das Problem zu sein. Wie schaut der Import aus? Wird alles auf einmal geholt? Hier ware "batchweisen" Laden mMn vorteilhafter.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
klingt auf den ersten blick nach einer unendlichschleife. hast du ma geguckt ob die schleife wirklich ein reales ende hat? habe auch solche funktionen zum einsatz mit den gleichen und höheren Datenmengen und das braucht eigentlich nicht soviel speicher.
haste mal ein codeausschnitt?
@ gfoidl
Hol mir die benötigten Daten mit den IDs und lade diese in einen DataTable. Mit diesen IDs werden die dazugehörigen Informationen ermittelt, sprich erneuter zugriff auf die DB, und dann in ein List<object> gespeichert.
@Equilibrium
es ist keine endlosschleife da es ja auch eine foreach - Schleife ist.
Wieviele Spalten hatten deine Tabelle meine hat über 140 Spalten.
Die Art und Weise wie du die Daten holst ist falsch. Lade immer nur einen begrenzten Satz an Daten und schreibe diesen in den Stream. Dann hole den nächsten Satz usw..
es ist keine endlosschleife da es ja auch eine foreach - Schleife ist.
hat nicht nur was mit der foreach zutun, kann auch an dem inhalt liegen der innerhalb der foreach verarbeitet wird, aber ohne code ist das schwer zu beurteilen. klingt nur sehr danach, weils typisch für diese art fehler ist.
kannst du ein codeauszug geben? manchmal ist es was absolut banales, was man total übersieht (eigene erfahrung)
@Equilibrium:
es ist keine Endlosschleife. Die Datenmenge ist das erschlagende. Hier wird ein Dataset mit 300.000 Datensätzen a 140 Spalten befüllt.... da knallt es schon beim einlesen wegen der schieren Anzahl an objekten.
@Arithmetika
Der Export ergibt 140 Spalten nicht der Import der Daten. Geladen werden nur die benötigten IDs um dann die geforderten informationen aus der DB zu fischen und dieser werden in eine List übertragen und dann über den StreamWriter in eine CSV Datei geschriebeb. Die List wird immer wieder neu befüllt und übergeben.
@Equilibrium
hier mal nen zusammengebastelter code snippet 😉
swrTempFile = new StreamWriter(strExportFilePath, false, System.Text.Encoding.Default);
IEnumerable<DataRow> objHotelRowsSelected = objHotelTable.Rows.Cast<DataRow>();
foreach(DataRow objDataRow in objHotelRowsSelected)
{
objExportList.Clear();
objExportList.Capacity = objExportTable.Columns.Count;
for (int i = 0; i < objExportList.Capacity; i++)
objExportList.Add(null);
strVar1 = string.Empty;
strVar2 = string.Empty;
strVar3 = string.Empty;
strVar1 = objExport.Var1
strVar2 = objExport.Var2;
strVar3 = objExport.Var3;
objExportList[0] = strVar1;
objExportList[1] = strVar2;
objExportList[2] = strVar3;
objDataRowExport = FillDataRowWithList(objExportTable.NewRow(),objExportList);
if (null != objDataRowExport)
{
for (int i = 0; i < intColumsCount; i++)
{
if(objDataRowExport[i] != null)
swrTempFile.Write('"' + objDataRowExport[i].ToString() + '"');
else
swrTempFile.Write('"' + string.Empty + '"');
if (i < intColumsCount - 1)
swrTempFile.Write(";");
}
swrTempFile.Write(swrTempFile.NewLine);
}
}
Hallo,
wie groß ist der Wert bei
objExportList.Capacity = objExportTable.Columns.Count;
denn dort wird die List<T> (?) auf die Größe gesetzt.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Hallo,
aus dem Code-Snippet kann man keinen konkreten Fehler erkennen.
Am besten, du benutzt einen Memory-Profiler, z.B. http://memprofiler.com/ (als Trial zum Download).
Der kann dir dann am besten sagen, wo du Speicherlecks hast (z.B. fehlende Dispose() bzw. using-Anweisungen).
Hi,
ich hab nicht so viel gemacht mit StreamWritern.
Schau doch mal: TextWriter.Flush-Methode
Wird der Reserviertespeicher vom Stream nicht durch Flush/AutoFlush frei?
MfG
Björn
Das Leben ist schön!
Ich würde das Lesen der Daten aus der Datenbank nicht per Dataset / Datatable sondern per DataReader vornehmen.
Braucht kaum Speicher, geht schneller und der Anwender kann den Exportvorgang auch abbrechen wenn er länger dauern sollte.
Grüße Bernd
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3