Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Einführung in Typed DataSets

Geschrieben von: Alexander Zeitler
Kategorie: ADO.NET

This printed page brought to you by AlphaSierraPapa

Eine Neuerung, die mit ADO.NET eingeführt wurde, sind die sogenannten DataSets, welche eine oder mehrere Datentabellen im Speicher abbilden. Hierzu werden die Namen der Spalten und die Daten des Abfrageergebnisses aus der Datenbank über den Namen als Strings angesprochen. Doch eben diese Art der Speicherung kann in der Praxis zu Problemen führen. Die Lösung ist Gegenstand dieses Artikels und heißt "Typed DataSets".

Nachteile normaler DataSets

Die Verwendung normaler DataSets sieht in der Praxis wie folgt aus (ClassicDataSet.aspx):

// Verbindung zur DB definieren
OleDbConnection MyNWConn = 
    new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" + 
    Server.MapPath("NWind.mdb"));

// DataSet erzeugen
DataSet MyDataSet = new DataSet();

// OleDbDataApter und OleDbCommand erzeugen
OleDbDataAdapter oCommand	= new OleDbDataAdapter();
OleDbCommand oledbcmd		= new OleDbCommand();

// SQL-String defnieren
oledbcmd.CommandType 	= CommandType.Text;
oledbcmd.CommandText 	= "SELECT * FROM Customers";

// Connection und SQL-String zuweisen
oledbcmd.Connection		= MyNWConn;
oCommand.SelectCommand	= oledbcmd;

// DataSet befüllen
oCommand.Fill(MyDataSet,"Events");

// Connection schließen
MyNWConn.Close();

// Daten aus dem DataSet ausgeben
foreach(DataRow dr in MyDataSet.Tables["Customers"].Rows)
{
    Response.Write(dr["CompanyName"] + "<br>");
} 

Interessant sind letztlich nur die beiden letzten Zeilen - wie man dort sieht, werden sowohl die Tabelle(n) als auch die Spalten über den Namen als Strings der entsprechenden Klassen (z.B. DataColumn) angesprochen.

Hierdurch ergeben sich zwei Nachteile: zum einen verliert man nach dem Lesen der Daten aus der Datenbank die Typisierung des Abfrageergebnisses, d.h. man weiß nicht mehr, ob in der Datenbank ein String, ein Integer oder ein Datum stand. Dies hat zur Folge, daß man die Abfrageergebnisse vor der weiteren Verwendung in lokalen Variablen erst casten muß, etwa so:

int myInt = int.Parse(dr["IntFeldInDerDB"].ToString());

Dies wiederum ist natürlich sehr anfällig gegen Tipp- und Denkfehler - man versucht ein Integer-Feld in der Datenbank in ein Datum zu casten oder vergißt schlicht ein Zeichen. Solche Fehler werden weder beim kompilieren in Visual Studio .NET noch mittels csc.exe erkannt. Im schlimmsten Fall ist der Kunde der erste, der den Fehler bemerkt.

Der zweite Nachteil findet sich ebenfalls in Visual Studio .NET wieder: der Verlust der IntelliSense. Da Visual Studio .NET für die abgebildete Datenstruktur keinerlei Schemainformationen besitzt, muß man auf die liebgewonnene Eingabehilfe verzichten. Das Ergebnis auch hier: Tippfehler.

Abhilfe: Typed DataSets

Die Lösung dieser Probleme stellen sogenannte Typed DataSets dar. Sie stellen eine Ableitung von System.Data.DataSet dar - dem klassischen DataSet also. Der große Unterschied hierzu liegt jedoch in der Implementierung der Spalten und Tabellen-Namen.

Diese werden nicht wie beim normalen DataSet als Strings abgelegt, sondern durch typsichere Eigenschaften mit dem der Datenbank entsprechenden Datentyp, d.h. ein Integer in der Datenbank bleibt auch nach dem Auslesen ein Integer. Ebenso gibt es für alle anderen Datenbankdatentypen die Entsprechungen. Datenbanktabellen und Zeilen werden durch eigene Klassen abgebildet.

Erzeugung von Typed DataSets

Die Frage, die Sie sich nun stellen werden: Wie erstelle ich ein solches Typed DataSet?

Die Erzeugung von Typed DataSets basiert darauf, zunächst eine Datei in der XML Schema Definition Language (XSD) zu erzeugen, welche die Struktur der Datenbank-Tabelle repräsentiert. Hierzu bedienen wir uns des normalen DataSets, welches eine Methode zur Erzeugung von XSD-Files aus einem bestehenden DataSet beinhaltet.

Die Erzeugung des XSD-Files sieht wie folgt aus (CreateTypedDataSet.aspx):

// Verbindung zur DB definieren
OleDbConnection MyNWConn = 
    new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" + 
    Server.MapPath("Nwind.mdb"));

// DataSet erzeugen
DataSet MyDataSet = new DataSet();

// OleDbDataApter und OleDbCommand erzeugen
OleDbDataAdapter oCommand	= new OleDbDataAdapter();
OleDbCommand oledbcmd		= new OleDbCommand();

// SQL-String defnieren
oledbcmd.CommandType 	= CommandType.Text;
oledbcmd.CommandText 	= "SELECT * FROM Customers";

// Connection und SQL-String zuweisen
oledbcmd.Connection		= MyNWConn;
oCommand.SelectCommand	= oledbcmd;

// DataSet befüllen
oCommand.Fill(MyDataSet,"Customers");

// Connection schließen
MyNWConn.Close();

// Daten aus dem DataSet in XSD-Datei speichern
MyDataSet.DataSetName = "CustomersDataSet";
MyDataSet.Tables[0].TableName = Customers";
MyDataSet.WriteXmlSchema(Server.MapPath("Customers.xsd"));

Zunächst lesen wir die gewünschte Tabelle, aus der die Schema-Informationen erzeugt werden sollen, aus und befüllen hiermit unser DataSet "MyDataSet". Die DataSet-Klasse stellt zum Erzeugen von XSD-Dateien die Methode WriteXmlSchema bereit, welche wir aufrufen, nachdem wir den Namen unseres DataSets und der darin enthaltenen DataTable zugewiesen haben.

Die Datei Customers.xsd befindet sich nun in unserem Projektordner. Was jetzt noch fehlt, ist die Generierung der CustomersDataSet-Klasse aus unserer XSD-Datei. Auch hierfür stellt das .NET-Framework ein Kommandozeilen-Tool bereit: xsd.exe. Dieses dient dazu, Schema- oder Klassendateien aus der angegebenen Quelle zu erzeugen. Um ein Typed DataSet aus der Customers.xsd zu erzeugen, ist folgender Aufruf notwendig:

Xsd.exe /d /l:C# Customers.xsd

Der Parameter /d gibt hierbei an, daß ein Typed DataSet erzeugt werden soll, /l:C# weist Xsd an, daß eine C#-Klassendatei erstellt werden soll.

Nun muß die erzeugte Klasse noch zu unserem Projekt hinzugefügt werden:

Verwenden von Typed DataSets

Die Verwendung von Typed DataSets (TypedDataSet.aspx) ist ähnlich wie bei normalen DataSets:

// Verbindung zur DB definieren
OleDbConnection MyNWConn = 
    new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" + 
    Server.MapPath("Nwind.mdb"));
	
// DataSet erzeugen
CustomersDataSet MyDataSet = new CustomersDataSet();

// OleDbDataApter und OleDbCommand erzeugen
OleDbDataAdapter oCommand	= new OleDbDataAdapter();
OleDbCommand oledbcmd		= new OleDbCommand();

// SQL-String definieren
oledbcmd.CommandType 	= CommandType.Text;
oledbcmd.CommandText 	= "SELECT * FROM Customers";

// Connection und SQL-String zuweisen
oledbcmd.Connection		= MyNWConn;
oCommand.SelectCommand	= oledbcmd;

// DataSet befüllen
oCommand.Fill(MyDataSet, "Customers");

// Connection schließen
MyNWConn.Close();


// Daten aus dem DataSet ausgeben
foreach(CustomersDataSet.CustomersRow dr in MyDataSet.Customers)
{
    Response.Write(dr.CompanyName + "<br>");
}

Die entscheidenden Änderungen sind in der Instanzierung des DataSets sowie dem Zugriff auf die Datenspalten und Tabellen zu finden.

Anstelle von Strings werden wie eingangs bereits erwähnt zur Abbildung der Tabellen (hier: MyDataSet.Customers) und Zeilen (hier: CustomersDataSet.CustomersRow) nun eigene Klassen verwendet. Die Spalten werden als Eigenschaften (hier: dr.CompanyName) dargestellt.

Zum Beweis, daß die Typisierung nun vorhanden ist, ein weiterer Screenshot aus VisualStudio.NET:

Und auch die versprochene IntelliSense-Unterstützung ist nun gewährleistet:

Wenn Sie nun einen Blick in die erzeugten Methoden unserer Typed DataTable werfen, werden Sie z.B. die Methode IsCompanyNameNull() entdecken. Diese bietet Ihnen die Möglichkeit, zu prüfen, ob die Spalte Daten beinhaltet - diese Prüfung sollte auch generell durchgeführt werden, bevor Daten aus einer Typed DataTable-Spalte ausgegeben werden, sonst kann man unangenehme Fehlermeldungen zur Laufzeit erhalten.

Schlußbemerkung

Damit sind wir am Ende unserer Einführung in Typed DataSets. Wie man sieht, kann man mit relativ geringem Aufwand die Stabilität einer Applikation im Bereich des Datenbanklayers durchaus verbessern - allerdings machen Typed DataSets nur dann Sinn, wenn sich die Struktur der Daten nicht ständig ändert: aber man kann die Generierung der Typed DataSets ja auch in den Buildprozess einhängen.

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20040622.zip

Verwandte Artikel

Das DataTable Objekt in ADO.NET
http:/www.aspheute.com/artikel/20001116.htm
DataViews als DataTable persistieren
http:/www.aspheute.com/artikel/20040123.htm
Datenbankzugriff mittels ADO.NET
http:/www.aspheute.com/artikel/20001102.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.