Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 5. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Weitere .NET-Datentypen
7 Weitere Möglichkeiten von C#
8 Auflistungsklassen (Collections)
9 Fehlerbehandlung und Debugging
10 LINQ to Objects
11 Multithreading und die Task Parallel Library (TPL)
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 Einige wichtige .NET-Klassen
15 Projektmanagement und Visual Studio 2010
16 XML
17 WPF – Die Grundlagen
18 WPF-Containerelemente
19 WPF-Steuerelemente
20 Konzepte der WPF
21 Datenbindung
22 2D-Grafik
23 ADO.NET – verbindungsorientierte Objekte
24 ADO.NET – Das Command-Objekt
25 ADO.NET – Der SqlDataAdapter
26 ADO.NET – Daten im lokalen Speicher
27 ADO.NET – Aktualisieren der Datenbank
28 Stark typisierte DataSets
29 LINQ to SQL
30 Weitergabe von Anwendungen
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual C# 2010 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2010

Visual C# 2010
geb., mit DVD
1295 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1552-7
Pfeil 26 ADO.NET – Daten im lokalen Speicher
Pfeil 26.1 »DataSet«-Objekte verwenden
Pfeil 26.1.1 »DataSet«-Objekte erzeugen
Pfeil 26.1.2 Anatomie einer »DataTable«
Pfeil 26.1.3 Zugriff auf eine Tabelle im »DataSet«
Pfeil 26.1.4 Zugriff auf die Ergebnisliste
Pfeil 26.1.5 Dateninformationen in eine XML-Datei schreiben
Pfeil 26.2 Gültigkeitsprüfung im »DataSet«
Pfeil 26.2.1 Dem »DataSet« Schema-Informationen übergeben
Pfeil 26.2.2 Eigenschaften einer »DataColumn«, die zur Gültigkeitsprüfung dienen
Pfeil 26.2.3 Die »Constraints«-Klassen einer »DataTable«
Pfeil 26.2.4 Schema mit Programmcode erzeugen
Pfeil 26.2.5 Schema-Informationen mit »SqlDataAdapter« abrufen
Pfeil 26.3 Änderungen in einer DataTable vornehmen
Pfeil 26.3.1 Editieren einer DataRow
Pfeil 26.3.2 Datenzeile löschen
Pfeil 26.3.3 Neue Datenzeile hinzufügen
Pfeil 26.3.4 Der Sonderfall: Autoinkrementspalten
Pfeil 26.3.5 Was passiert bei der Änderung einer Datenzeile?
Pfeil 26.3.6 Manuelles Steuern der Eigenschaft »DataRowState«
Pfeil 26.4 Mit mehreren Tabellen arbeiten
Pfeil 26.4.1 Der Weg über JOIN-Abfragen
Pfeil 26.4.2 Mehrere Tabellen in einem »DataSet«
Pfeil 26.4.3 Eine »DataRelation« erzeugen
Pfeil 26.4.4 »DataRelation« und Einschränkungen
Pfeil 26.4.5 In Beziehung stehende Daten suchen
Pfeil 26.4.6 Ergänzung zum Speichern von Schema-Informationen in einer XML-Schema-Datei
Pfeil 26.5 Filtern und Suchen in einer DataTable
Pfeil 26.5.1 Die Methode »Find«
Pfeil 26.5.2 Die Methode »Select«
Pfeil 26.6 Objekte vom Typ »DataView«
Pfeil 26.6.1 »DataView« erzeugen
Pfeil 26.6.2 Auf die Datenzeilen in einer »DataView« zugreifen
Pfeil 26.6.3 Die Eigenschaft »Sort« und die Methode »Find«
Pfeil 26.6.4 Die Methode »FindRows«
Pfeil 26.6.5 Die Eigenschaft »RowFilter«
Pfeil 26.6.6 Die Eigenschaft »RowStateFilter«
Pfeil 26.6.7 Änderungen an einem »DataView«-Objekt
Pfeil 26.6.8 Aus einer »DataView« eine »DataTable« erzeugen

26 ADO.NET – Daten im lokalen Speicher

Wäre man gezwungen, eine Rangfolge der ADO.NET-Typen nach ihrer Wichtigkeit aufzustellen, würde DataSet zweifelsfrei an erster Position stehen. Diese Klasse bildet den Kern von ADO.NET, um den herum sich fast alles andere rankt.

Ein DataSet ist in erster Linie ein Datencontainer. Organisiert und verwaltet werden die Daten in Form von Tabellen. Wenn Sie sich darunter Tabellen ähnlich denen von Microsoft-Excel vorstellen, liegen Sie gar nicht so falsch. Ob es sich um eine oder auch mehrere Tabellen handelt, hängt von der zugrunde liegenden Abfrage ab, die durch das SqlCommand-Objekt beschrieben wird. Enthält das DataSet mehrere Tabellen, so können zwischen den Tabellen Beziehungen eingerichtet werden – ganz so wie in der Originaldatenbank.

In Kapitel 24, »ADO.NET – Das Command-Objekt«, haben Sie den Typ SqlDataReader kennengelernt. Mit einem Objekt dieses Typs können Sie Daten basierend auf einer Abfrage abrufen. Ein SqlDataReader ist aber nicht so weit ausgebildet, dass er die üblichen Aufgaben einer Datenbankanwendung erfüllen kann. Wie Sie wissen, können Sie nur vorwärts navigieren, zudem sind die Daten schreibgeschützt. Damit ist der SqlDataReader in seiner Funktionalität sehr eingeschränkt, er ist allerdings enorm effizient, denn er ist auf Performance ausgelegt. Ein DataSet hingegen bietet Ihnen im Vergleich dazu deutlich mehr Funktionalitäten, schneidet hinsichtlich der Performance aber schlechter ab.

Die Daten im DataSet stehen in keinem Kontakt zur Datenbank. Nachdem das DataSet über das SqlDataAdapter-Objekt gefüllt worden ist, gibt es keine Verbindung zwischen DataSet und Datenbank mehr. Nimmt ein Anwender Änderungen an den Daten vor, schreiben sich diese nicht sofort in die Originaldatenbank zurück, sondern werden vielmehr zunächst im DataSet gespeichert. Zum Zurückschreiben der geänderten Daten muss ein Anstoß erfolgen. Häufig kann man sich dazu wieder des SqlDataAdapters bedienen, der die notwendige Aktualisierungslogik bereitstellt. Sollten Sie Erfahrungen mit Datenbanken haben, werden Sie jetzt sicherlich sofort einwenden, dass damit Konfliktsituationen vorprogrammiert sind, wenn ein zweiter Anwender zwischenzeitlich Änderungen am gleichen Datensatz vorgenommen hat. Der Einwand ist korrekt, andererseits gibt uns ADO.NET alle Mittel an die Hand, um eine benutzerdefinierte Konfliktsteuerung und Konfliktanalyse zu codieren. Darüber hinaus können Sie eine Konfliktlösung realisieren, ganz so, wie es Sie es sich vorstellen. Mit der Aktualisierung der Originaldatenbank werden wir uns in diesem Kapitel jedoch noch nicht beschäftigen.

Damit sind noch nicht alle Fähigkeiten des DataSets erwähnt. In einem DataSet lässt sich die Ansicht der Abfrageergebnisse ändern. Sie können die Daten basierend auf einer oder mehreren Spalten sortieren. Setzen Sie im DataSet einen Filter, sehen Sie nur Daten, die bestimmte Kriterien erfüllen. Zudem ist die Zusammenarbeit eines DataSets mit XML ausgezeichnet. Der Inhalt eines DataSets kann als XML-Dokument in einer Datei gespeichert und der Inhalt einer XML-Datei in ein DataSet eingelesen werden. Darüber hinaus lassen sich die Schema-Informationen eines DataSets in einer XML-Schema-Datei speichern.


Galileo Computing - Zum Seitenanfang

26.1 »DataSet«-Objekte verwenden Zur nächsten ÜberschriftZur vorigen Überschrift


Galileo Computing - Zum Seitenanfang

26.1.1 »DataSet«-Objekte erzeugen Zur nächsten ÜberschriftZur vorigen Überschrift

Die Klasse DataSet befindet sich, wie viele andere Klassen auch, die nicht providerspezifisch sind, im Namespace System.Data. In den meisten Fällen ist der parameterlose Konstruktor vollkommen ausreichend, um ein DataSet-Objekt zu erzeugen.


DataSet ds = new DataSet();

Soll das DataSet einen Namen erhalten, bietet sich alternativ der einfach parametrisierte Konstruktor an:


DataSet ds = new DataSet("Bestellungen");

Der Name kann auch über die Eigenschaft DataSetName festgelegt oder abgerufen werden.


Galileo Computing - Zum Seitenanfang

26.1.2 Anatomie einer »DataTable« Zur nächsten ÜberschriftZur vorigen Überschrift

Zum Leben erweckt wird ein DataSet-Objekt nicht durch die Instanziierung der Klasse, sondern vielmehr durch den Aufruf der Fill-Methode des DataAdapters:


...
string strSQL = "SELECT * FROM Products";
SqlDataAdapter da = new SqlDataAdapter(strSQL, con);
DataSet ds = new DataSet();
da.Fill(ds);
...

Das Ergebnis der Abfrage enthält alle Datensätze der Tabelle Products. Die Datensätze sind in einer Tabelle enthalten, die durch ein DataTable-Objekt beschrieben wird. Ein DataTable-Objekt beschreibt die Spalten, die im SELECT-Statement der Abfrage angegeben sind. Jede Spalte wird dabei als Objekt vom Typ DataColumn behandelt. Um eine einfache Verwaltung und einen einfachen Zugriff auf bestimmte Spalten zu gewährleisten, werden alle Spalten in eine Auflistung der DataTable eingetragen. Über die Eigenschaft Columns der DataTable erhalten Sie Zugriff auf die DataColumnCollection.

In ähnlicher Weise ist auch das Ergebnis der Abfrage organisiert. Jeder zurückgelieferte Datensatz wird durch ein Objekt vom Typ DataRow beschrieben. Alle Datenzeilen in einer Tabelle werden von einer Auflistung verwaltet, der DataRowCollection, auf die Sie über die DataTable-Eigenschaft Rows zugreifen können.

Eine DataTable hat eine DataColumn- und eine DataRowCollection. Da ein DataSet nicht nur eine, sondern prinzipiell beliebig viele Tabellen enthalten kann, muss auch der Zugriff auf eine bestimmte DataTable im DataSet möglich sein. Wie kaum anders zu erwarten ist, werden auch alle Tabellen in einem DataSet von einer Auflistung organisiert. Diese ist vom Typ DataTableCollection, deren Referenz die Eigenschaft Tables des DataSets liefert.

Abbildung 26.1 Die Struktur eines »DataSets«


Galileo Computing - Zum Seitenanfang

26.1.3 Zugriff auf eine Tabelle im »DataSet« Zur nächsten ÜberschriftZur vorigen Überschrift

Wenn ds das DataSet-Objekt beschreibt, genügt eine Anweisung wie die folgende, um auf eine bestimmte Tabelle im DataSet zuzugreifen:


ds.Tables[2]

Enthält das DataSet mehrere Tabellen, lassen sich die Indizes oft nur schwer einer der Tabellen zuordnen. Wie Sie wissen, weist der SqlDataAdapter per Vorgabe den Tabellen im DataSet ebenfalls Bezeichner (Table, Table1, Table2 usw.) zu. Sowohl die Indizes als auch die Standardbezeichner sind aber wenig geeignet, um den Code gut lesbar zu gestalten. Der SqlDataAdapter unterstützt eine DataTableMappingCollection, um lesbare Tabellennamen abzubilden. Zudem bietet die Überladung der Methode des SqlDataAdapters die Möglichkeit, einer Tabelle einen sprechenden Bezeichner zuzuordnen. Sie sollten eines dieser Angebote nutzen, denn die Anweisung


ds.Tables["Artikel"]

wird Ihnen später eher hilfreich sein, den eigenen Programmcode zu verstehen, als die Angabe eines nur schlecht zuzuordnenden Index.


Galileo Computing - Zum Seitenanfang

26.1.4 Zugriff auf die Ergebnisliste Zur nächsten ÜberschriftZur vorigen Überschrift

Ein DataRow-Objekt stellt den Inhalt eines Datensatzes dar und kann sowohl gelesen als auch geändert werden. Um in einer DataTable von einem Datensatz zum anderen zu navigieren, benutzen Sie Eigenschaft Rows der DataTable, die die Referenz auf das DataRowCollection-Objekt der Tabelle zurückgibt und alle Datensätze enthält, die Ergebnis der Abfrage sind. Die einzelnen DataRows sind über den Index der Auflistung adressierbar.

Mit der folgenden Anweisung wird der Verweis auf die dritte Datenzeile in der ersten Tabelle des DataSets der Variablen row zugewiesen:


DataRow row = ds.Tables["Artikel"].Rows[2];

Eine Datenzeile nur zu referenzieren, ist sicher nicht das von Ihnen verfolgte Ziel. Vielmehr werden Sie daran interessiert sein, den Inhalt einer oder mehrerer Spalten der betreffenden Datenzeile auszuwerten. Dazu veröffentlicht die DataRow einen Indexer, dem Sie entweder den Namen der Spalte, deren Index in der DataColumnCollection der DataTable (die Ordinalposition) oder die Referenz auf die gewünschte Spalte übergeben. Der Rückgabewert ist jeweils vom Typ Object und enthält die Daten der angegebenen Spalte. Häufig ist eine anschließende Konvertierung in den richtigen Datentyp notwendig. Wenn Sie die Überladung einsetzen, die den Spaltenbezeichner erwartet, müssen Sie zwei Ausgangssituationen beachten: Per Vorgabe setzen Sie diejenigen Spaltenbezeichner ein, die auch in der Originaldatenbank bekannt sind. Haben Sie jedoch der DataColumnMappingCollection Spaltenzuordnungen hinzugefügt, müssen Sie diese angeben.

Wir wollen uns dies nun an einem Beispiel ansehen.


// ------------------------------------------------------------------
// Beispiel: ...\Kapitel 26\ShowDataRows
// ------------------------------------------------------------------
class Program {
  static void Main(string[] args) {
    SqlConnection con = new SqlConnection();
    con.ConnectionString = "...";
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;
    cmd.CommandText = "SELECT ProductName, UnitPrice " +
                      "FROM Products " +
                      "WHERE UnitsOnOrder > 0";
    DataSet ds = new DataSet();
    SqlDataAdapter da = new SqlDataAdapter(cmd);
    da.Fill(ds, "Artikel");
    // Ausgabe der Ergebnisliste
    DataTable tbl = ds.Tables["Artikel"];
    for (int i = 0; i < tbl.Rows.Count; i++) {
      Console.WriteLine("{0,-35}{1}",
        tbl.Rows[i]["ProductName"], tbl.Rows[i]["UnitPrice"]);
    }
    Console.ReadLine();
  }
}

Gefragt ist nach allen Artikeln, zu denen aktuell Bestellungen vorliegen. Nach dem Füllen des DataSets wird die Ergebnisliste in einer Schleife durchlaufen. Der Schleifenzähler wird dabei als Index der Datenzeile eingetragen. Damit die einzelnen Anweisungen nicht zu lang werden, wird vor Beginn des Schleifendurchlaufs die DataTable im DataSet in einer Variablen gespeichert.


DataTable tbl = ds.Tables["Artikel"];

Da alle Datenzeilen von einer Auflistung verwaltet werden, stehen die üblichen Methoden und Eigenschaften zur Verfügung. In diesem Code wird die Eigenschaft Count abgefragt, um festzustellen, wie viele Datenzeilen sich in der Ergebnisliste befinden.

Sie können auch statt der for-Schleife eine foreach-Schleife einsetzen. Der folgende Codeausschnitt ersetzt daher vollständig die for-Schleife unseres Beispiels:


foreach(DataRow row in tbl.Rows)
  Console.WriteLine("{0,-35}{1}", row["ProductName"], row["UnitPrice"]);


Galileo Computing - Zum Seitenanfang

26.1.5 Dateninformationen in eine XML-Datei schreiben topZur vorigen Überschrift

Sie können die Dateninformationen eines DataSets in eine XML-Datei schreiben und später im Bedarfsfall auch wieder laden. Hierzu stehen Ihnen mit WriteXml und ReadXml die passenden Methoden zur Verfügung, die auf die Referenz des DataSet-Objekts aufgerufen werden. Beiden Methoden können Sie als Parameter den Namen der Datei mitgeben, in die die Daten gespeichert bzw. aus der die XML-Daten gelesen werden sollen:


ds.WriteXml(@"D:\Daten\ContentsOfDataset.xml");
...
ds.ReadXml(@"D:\Daten\ContentsOfDataset.xml");

Der Parameter beschränkt sich nicht nur auf Dateien. Sie können auch einen TextReader, einen Stream oder einen XmlReader angeben.

Nachfolgend sehen Sie den Teilausschnitt eines XML-Dokuments, dem die Abfrage


SELECT ProductID, ProductName FROM Products

zugrunde liegt.


<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <Table>
    <ProductID>1</ProductID>
    <ProductName />
  </Table>
  <Table>
    <ProductID>17</ProductID>
    <ProductName>Alice Mutton</ProductName>
  </Table>
  <Table>
    <ProductID>3</ProductID>
    <ProductName>Aniseed Syrup</ProductName>
  </Table>
  <Table>
    <ProductID>40</ProductID>
    <ProductName>Boston Crab Meat</ProductName>
  </Table>
  <Table>
    <ProductID>60</ProductID>
    <ProductName>Camembert Pierrot</ProductName>
  </Table>
  ...
</NewDataSet>



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual C# 2010

Visual C# 2010
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: C/C++






 C/C++


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2010
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern