Verwendetes Datenbanksystem: ADO.net
Hallo Forum,
mich beschäftigt gerade wieder eine Frage: Ich habe ein DataSet mit typisiertem DataTable, das ich in eine Xml schreibe. Diese Xml lese ich zu einem späteren Zeitpunkt wieder ein und ich möchte die Daten in eine List<T> eintragen. Das Ganze funktioniert auch. Leider geht die Typzuordnung verloren. In Summe besteht die DataRow aus 50+ Columns mit unterschiedlichen Datentypen.
Hier das anbgespeckte Beispiel mit nur 2 Columns:
public DataSet ProjektDataSet = new DataSet();
public DataTable ProjekteDataTable = new DataTable();
DataColumn IDNrHaupt = new DataColumn("IDNrHaupt", typeof(Int32));
ProjekteDataTable.Columns.Add(IDNrHaupt);
DataColumn IDNrNeben = new DataColumn("IDNrNeben", typeof(Int32));
ProjekteDataTable.Columns.Add(IDNrNeben);
ProjekteDataTable.TableName = "Projekte";
ProjektDataSet.ReadXml(Anwendungsdaten2, XmlReadMode.ReadSchema);
foreach (DataRow DR in ProjektDataSet.Tables["Projekte"].Rows)
{
Projekte.Add(new ClassProjekt()
{
IDNrHaupt = DR["IDNrHaupt"],
IDNrNeben = Int32.Parse(DR["IDNrNeben"].ToString())
});
}
Warum versteht C# nicht, dass das Feld DR["IDNrHaupt"] ein Int32 ist? Dort wird ein Fehler "Cannot iplicity convert type 'object' to 'int'" ausgegeben. Warum muss ich wie bei IDNrNeben gezeigt, den Weg der doppelten Konvertierung über ToString nach INT32 gehen mit dem Risiko der Missinterpretation von Kommas bei Double Variablen? Wie muss ich meinen Code gestalten, damit die doppelte Konvertierung überflüssig wird?
Danke für Euren Support.
NoSonOfMine
Zitat von NoSonOfMine
Warum versteht C# nicht, dass das Feld DR["IDNrHaupt"] ein Int32 ist?
C# ist nur eine Sprache und keine Runtime, was Du meinst ist .NET.
.NET als Runtime kann das nicht wissen, weil eine Zelle prinzipiell jede Art von Typ sein kann. Daher ist der Inhalt vom Typ object
und nicht int.
Weil die ganze Arbeit mit solchen DataTables nicht unbedingt so cool ist - eben wegen dem Typ-Handling - gilt die Arbeit mit dem DataSet auch als veraltet an. Die bessere Art und Weise ist das Binden von Daten und nicht die aktive Verwendung von UI Controls.
Funktionsbeispiel: How to: Bind data to the Windows Forms DataGridView control
Klar, rein technisch kannst weiter mit DataTable und Co arbeiten - aber dann bist Du für jedes Handling durch manuelle Arbeit in der Verantwortung.
Daher
Wie muss ich meinen Code gestalten, damit die doppelte Konvertierung überflüssig wird?
Geht im Endeffekt nur, wenn Du DataBindings verwendest. Und unter Windows Forms wirst Du immer gewisse Dinge manuell machen müssen, anders bei WPF, das vollständig auf MVVM und Bindings setzt. WinForms hat keinen direkten Pattern, jedoch ist der Model-View-Pattern und DataBinding empfohlen, wo es angeboten wird.
Warum muss ich wie bei IDNrNeben gezeigt, den Weg der doppelten Konvertierung über ToString nach INT32 gehen mit dem Risiko der Missinterpretation von Kommas bei Double Variablen?
Weil Du ansonsten keinerlei Lokalisierung (dazu gehört nicht nur die Sprache sondern auch Regionseinstellungen wie Formatierungen) umsetzen kannst. Du musst bzw. sollst (auch laut Guidelines) bei jedem Umgang mit Werten (Zahlen, Ziffern, Datumswerten..) die Culture-Beachten. Daher haben alle Methoden, bei denen man sowas beachten muss, auch einen CultureInfo Parameter.
Beachtest Du das nicht, dann kann es sein, dass Deine User je nach PC-Einstellung Probleme bekommen. Ich zB hab eine Steuer-Software, die mit .NET geschrieben ist, die falsche Steuererklärungen generiert, wenn mein PC keine Deutsche Regionseinstellung hat - super!
Antwort des Herstellers: "ist halt für Deutsche gemacht". Aber wohl nicht für Deutsche, die andere Regionseinstellungen haben.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Wenn du als Entwickler weißt, daß es sich um einen bestimmten Typ handelt, dann kannst du auch einfach casten:
IDNrHaupt = (int)DR["IDNrHaupt"],
IDNrNeben = (int)DR["IDNrNeben"]
bzw. bei Referenztypen mittels [FAQ] Casten aber richtig: Boxing/Unboxing - () / is / as / Pattern Matching.
Den Weg der doppelten Konvertierung musst du nicht gehen, es reicht ein simpler Cast IDNrHaupt = (int)DR["IDNrHaupt"]
EDIT: Oh, zwei Stühle eine Meinung ...
Hat die Blume einen Knick, war der Schmetterling zu dick.
Wie wird beim einfachen Cast, z.B.
SOP = (DateTime)DR["SOP"];
Zahl = (Double)DR["Zahl"];
die
CultureInfo.InvariantCulture
berücksichtigt? Dabei fällt mir auf, dass ich das auch nicht bei einem doppelten Konvertieren wüsste?!?
Casten bedeutet, dass Du ein Objekt hast, das bereits den Zieltyp hat oder direkt dahin gecastet werden kann.
Casting and type conversions (C# Programming Guide)
Wenn Du ein String mit irgendeinem Format (DateTime, Double.. Whatever) hast, wo Du die Culture beachten musst, dann kannst Du nicht einfach so nach Double, DateTime...casten.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code