Hallo, ich lese zwar schon länger in diesem Forum mit, aber das hier mein erster Thread.
Ich hoffe ich habe alle Regeln befolgt 😃.
Zur meinem Problem:
Ich bekomme folgende Exception, wenn ich eine große DataTable (ca. 2000 x 20000 Zellen) versuchte von deserialisieren (egal ob mit BinaryFormatter oder XmlSerializer):
'Eine nicht behandelte Ausnahme des Typs "System.StackOverflowException" ist in System.Xml.dll aufgetreten.'
Ich serialisiere das DataTable mit (im Falle des XmlSerializer):
public static void XMLSerialisieren<T>(T objekt, string path)
{
XmlSerializer mySerializer = new XmlSerializer(typeof(T));
StreamWriter myWriter = new StreamWriter(path);
mySerializer.Serialize(myWriter, objekt);
myWriter.Close();
myWriter.Dispose();
}
und deserialisiere es mit :
public static void XMLDeserialisieren<T>(out T objekt, string path)
{
XmlSerializer ser = new XmlSerializer(typeof(T));
StreamReader sr = new StreamReader(path);
objekt = (T)ser.Deserialize(sr);
sr.Close();
sr.Dispose();
}
Am Speicher sollte es nicht liegen, ich hab 16GB (win7 x64).
Vielleicht kennt jemand eine Lösung.
Bei einschlägigen Suchmaschinen könnte ich keine Lösung finden!
Danke schonmal im Voraus.
verwendetes Datenbanksystem: <DataTable>
Ich bin mir nicht sicher, wie das serialisieren der Datatable intern abläuft, aber scheinbar ist deine schlicht und ergreifen zu groß (und ich würde auf zu "breit" tippen). StackOverflow tritt ja meistens bei ner zu großen Rekursionstiefe auf ...
Du könntest nun entweder versuchen jeweils nur einen Teil zu serialisieren (also zum Beispiel 4 Tabellen á 500 Spalten) oder du könntest versuchen diese kleineren zu serialisieren.
Ein weiterer Versuch wäre es die Tabelle erst in XML zu schreiben und dann selbiges zu Serialisieren.
Und als letztes fällt mir noch ein:
Schreib deinen eigenen Serialisierer - ist glaube ich gar nicht so schwer.
Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)
Danke für deine Antwort.
Das mit kleineren Tabellen wäre auch meine Notlösung gewesen, aber es wäre schon schön, wenn ich alles in einer Tabelle hätte.
Wie meinst du das mit, "erst in XML zu schreiben und dann selbiges zu Serialisieren"?
Du kannst eine DataTable meines wissens nach in eine XML-Struktur schreiben. Vielleicht funktioniert das (natürlich nur dann, wenn die Funktion nicht selbst den XML-Serializer benutzen sollte).
Mir fällt allerdings der Funktionsnamen grade nicht ein ...
Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)
[DataTable] .WriteXmlSchema();
Okay danke, ich versuche mal meine Daten in kleinere Tabellen zu schreiben.
2.000x20.000 Zellen?
Das sind 40.000.000 Zellen und da hast du gleich locker beim deserialisieren den gesamten speicher voll.
Warum meinst du so grosse DataTables benutzen zu müssen?
Naja anlegen könnte ich das DataTable ja problemlos und die serialisierte Tabelle ist 1 GB groß.
Müßte also auch in den Speicher passen.
Sind auch glaube keine 20.000 Spalten, eher weniger, war nur eine Schätzung und viele Werte sind ja DBNull.
Nocheimal, warum meinst du solche Monster benutzen zu müssen?
Was soll das wirklich geben?
Und eine DataTable musst du nicht serialisieren, da reicht ein Write/ReadXml
Wie frage ist doch nicht warum ich die Daten haben möchte, sondern warum .Net gesicherte Werte nicht wieder herzustellen kann (im Speicher passen sie ja!).
Aber da du gefragst, will ich dir auch antworten:
Die Tabelle ist eine Document-Term-Matrix, d.h. eine Zeile stellt ein Dokument dar und die Spalten sind die gestemmten Wörter und die DataTable ist hier sehr bequem mit ihrer SELECT - Funktion.
Ich weiß für richtig viele Daten gibt es bessere Repräsentationsarten hierfür als eine Matrix, z.B. in Form einer Inverted Index Liste.
Aber für dieses Problem ist die Datenmenge sehr überschaubar.
Und das Deserialisierungsproblem ist mir schon häufiger begegnet (nicht nur bei DataTables), und hab nie eine Antwort gefunden.
Mit Write/ReadXml hast du teilweise recht, Hatte ich auch vorher benutzt. Ich habe aber den XmlSerializer verwendet, da für ReadXml die Tabellenstruktur der Zieltabelle schon bekannt seien muss (was nicht der Fall ist).
Bill Gates said we should never need more than 64K of RAM
Hallo!
Mit Read/WriteXmlSchema kannst du auch die beschreibung der Tabelle festlegen bzw. einlesen.
EDIT: Dass dabei nur die Struktur geschrieben wird, ist beabsichtigt, damit unabhängig davon mehrere Datendateien erstellt werden können.
Nobody is perfect. I'm sad, i'm not nobody 🙁
Danke, aber WriteXmlSchema schreibt nur die Struktur ohne Daten!
Ich versuch mal:
.WriteXmlSchema(..)
.WriteXml(..)
...
.ReadXmlSchema(...)
.ReadXml(...)
ist zwar komplizierter und ich habe dann zwei Datei, aber ich probier es mal.
Leider funktioniert es auch so nicht!
Auch hier kommt beim Einlesen die Exception:
'Eine nicht behandelte Ausnahme des Typs "System.StackOverflowException" ist in System.Xml.dll aufgetreten.'
Sonst noch Ideen zur Frage der Exception (System.StackOverflowException)?
Der Stack ist nun mal begrenzt. Das hat auch nicht unbedingt was mit .NET zu tun. Und es ist auch niemand auf die Idee gekommen 40 Millionen Datenzellen zu Serialisieren oder zu Deserialisieren... In einem Stück.
Dabei ist es nicht mal die Menge der Rows, sondern eher die Exorbitante Anzahl an Columns, denn niemand auf der Welt kommt auf die Idee eine Tabelle mit 2000! Colums anzulegen... oder gar über die Idee einer Idee sowas zu machen nachzudenken. Das ist dann auch der Grund, warum du zu diesem Thema nichts findest.
Da du ohnehin schon mit Select & Co arbeitest... warum denn keine embedded Datenbank? Dann kannst du evtl. auch ein schönes, schlankes und vor allem Relationales Modell dahinter hängen und so das System übersichtlicher machen?
Und durch LinQ to Object zieht auch das Select nicht wirklich als Ausrede.
Bleibt die Erkenntnis, das alles seine Limitierung hat und nicht alles, was man Speichern/Serialisieren auch nachher noch laden kann.
Da werde ich dann ganz old-school meine eigenen Datenaustauschmethoden schreiben und die Werte in einer csv-Datei sichern, sind ja in diesem Fall nur strings und floats.
@JAck30lena: Es scheint aber nicht die Spaltenanzahl, sondern die Größe das Problem zu sein. Dieses Problem trat auch schon mal bei einer 100 x 6 Tabelle auf, da waren aber der Zellinhalt größer (längere strings).
- Nicht alles was einfach zu benutzen ist, ist auch für jedes Problem benutzbar.
- Natürlich kannst du bei WriteXml auch noch einen weiteren Parameter angeben, der das Schema mit schreibt.
- Beim einlesen der XML passieren ja viel mehr als "nur" die XML einzulesen und dann so wie sie ist in eine DT zu packen.
Und durch LinQ to Object zieht auch das Select nicht wirklich als Ausrede.
Ich glaube nicht, dass wen jemand eine Frage postet, er solche Antworten erwartet. Ich konnte es selber nicht glauben und hab seine Funktionen getestet mit dem gleichen Resultat. Als "Monster" würde ich das jetzt auch nicht bezeichnen. 1 GB Arbeitsspeicher für eine Tabelle ist doch kein Thema. Aus meiner Sicht ist das ein unbekannter Kompiler-Fehler in C# oder eine andere Lösung.
Sinn der Serialisierung sollte es doch sein jede Klasse (auch DT) im Speicher in eine Datei speichern zu können. Scheinbar macht er das auch, jedoch zurück kann er das dann nicht mehr.
Schließe mich also der Suche an...
Wenn du auf eine Frage immer erwartest das man dir bei der Herangehensweise recht gibt, ist die Frage als solche schon mal Sinnlos.
Wenn du den Prozess beim Deserialisieren nicht durchschaust, ist sicherlich 1GB "nicht viel", da du aber dabei haufenweise Zwischenobjekte erzeugst ist der vorhandene Speicher unter .NET recht schnell weg, zumal wie der OP feststellen musste einiges davon auf dem Stack passiert.
Es gibt Objekte, und die DT gehört dazu, die eine eigene Serialisierung bereitstellen, die speziell auf sie abgestimmt ist, und dann eine andere zu benutzen ist sehr kontraproduktiv.
Bei einer DT würde z.b. mit std Serialisierung versucht werden neben den Properties selber auch noch die Textrepresentation zu speichern.
Auch wenn Du es evtl nicht einsiehst, auch Kritik an der Herangehensweise kann Zielführend sein.