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

Inhaltsverzeichnis
Vorwort zur 6. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Das Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Strukturen und Enumerationen
7 Fehlerbehandlung und Debugging
8 Auflistungsklassen (Collections)
9 Generics – Generische Datentypen
10 Weitere C#-Sprachfeatures
11 LINQ
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 XML
15 Multithreading und die Task Parallel Library (TPL)
16 Einige wichtige .NET-Klassen
17 Projektmanagement und Visual Studio 2012
18 Einführung in die WPF und XAML
19 WPF-Layout-Container
20 Fenster in der WPF
21 WPF-Steuerelemente
22 Elementbindungen
23 Konzepte von WPF
24 Datenbindung
25 Weitere Möglichkeiten der Datenbindung
26 Dependency Properties
27 Ereignisse in der WPF
28 WPF-Commands
29 Benutzerdefinierte Controls
30 2D-Grafik
31 ADO.NET – Verbindungsorientierte Objekte
32 ADO.NET – Das Command-Objekt
33 ADO.NET – Der SqlDataAdapter
34 ADO.NET – Daten im lokalen Speicher
35 ADO.NET – Aktualisieren der Datenbank
36 Stark typisierte DataSets
37 Einführung in das ADO.NET Entity Framework
38 Datenabfragen des Entity Data Models (EDM)
39 Entitätsaktualisierung und Zustandsverwaltung
40 Konflikte behandeln
41 Plain Old CLR Objects (POCOs)
Stichwort

Download:
- Beispiele, ca. 62,4 MB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
Visual C# 2012 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2012

Visual C# 2012
Rheinwerk Computing
1402 S., 6., aktualisierte und erweiterte Auflage 2013, geb., mit DVD
49,90 Euro, ISBN 978-3-8362-1997-6
Pfeil 33 ADO.NET – Der SqlDataAdapter
Pfeil 33.1 Was ist ein DataAdapter?
Pfeil 33.2 Die Konstruktoren der Klasse DataAdapter
Pfeil 33.3 Arbeiten mit dem SqlDataAdapter
Pfeil 33.3.1 Die Eigenschaft »SelectCommand«
Pfeil 33.3.2 Den lokalen Datenspeicher mit »Fill« füllen
Pfeil 33.3.3 Öffnen und Schließen von Verbindungen
Pfeil 33.3.4 Doppelter Aufruf der Fill-Methode
Pfeil 33.3.5 Mehrere DataAdapter-Objekte aufrufen
Pfeil 33.3.6 Die Spalten- und der Tabellenbezeichner einer DataTable
Pfeil 33.3.7 Paging mit der Fill-Methode
Pfeil 33.4 Tabellenzuordnung mit der Klasse »TableMappings«
Pfeil 33.4.1 Spaltenzuordnungen in einem DataSet
Pfeil 33.4.2 Spaltenzuordnungen einer DataTable
Pfeil 33.4.3 Die Eigenschaft »MissingMappingAction« des DataAdapters
Pfeil 33.5 Das Ereignis »FillError« des SqlDataAdapters

Rheinwerk Computing - Zum Seitenanfang

33.3 Arbeiten mit dem SqlDataAdapterZur nächsten Überschrift


Rheinwerk Computing - Zum Seitenanfang

33.3.1 Die Eigenschaft »SelectCommand«Zur nächsten ÜberschriftZur vorigen Überschrift

Verwenden Sie den parameterlosen Konstruktor, müssen Sie der Eigenschaft SelectCommand die Referenz auf ein Command-Objekt zuweisen.

SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;

Die Klasse SqlDataAdapter stellt weder eine Eigenschaft noch eine Methode bereit, mit der wir eine Verbindungszeichenfolge oder ein SqlConnection-Objekt festlegen können. Das ist aber nicht von Bedeutung, da das SqlCommand-Objekt bereits selbst alle Verbindungsinformationen enthält.

string strCon = @"Data Source=.\sqlexpress;" +
"Initial Catalog=Northwind;Trusted_Connection=yes";
SqlConnection con = new SqlConnection(strCon);
SqlCommand cmd = new SqlCommand("SELECT * FROM Products", con);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;

Listing 33.2 DataAdapter-Eigenschaften festlegen


Rheinwerk Computing - Zum Seitenanfang

33.3.2 Den lokalen Datenspeicher mit »Fill« füllenZur nächsten ÜberschriftZur vorigen Überschrift

Es lässt sich trefflich darüber streiten, welche Methode eines bestimmten Typs die wichtigste ist. Bei einem SqlDataAdapter-Objekt sind es wohl zwei Methoden, die den Kern dieses Typs ausmachen:

  • die Methode Fill
  • die Methode Update

Mit Hilfe der Methode Fill wird der lokale Datenspeicher mit dem Ergebnis einer SELECT-Abfrage gefüllt. Dazu wird für die Dauer der Operation eine Verbindung zur Datenquelle geöffnet und nach ihrer Beendigung wieder geschlossen. Die empfangenen Daten werden in einem DataTable-Objekt vorgehalten, das sich in einem DataSet befindet. DataTable beschreibt alle Spalten, die in der SELECT-Abfrage angegeben sind; die Spaltenbezeichner werden aus der Originaldatenbank übernommen. Der Anwender kann die Daten ändern, Datensätze löschen oder neue hinzufügen. Während dieser Zeit besteht kein Kontakt zur Datenbank. Somit wird er (zunächst) nichts von den Änderungen im DataSet bzw. der DataTable erfahren.

Zu irgendeinem Zeitpunkt sollen die Änderungen natürlich in die Originaldatenquelle zurückgeschrieben werden. Dazu muss die Methode Update des SqlDataAdapters aufgerufen werden. Der SqlDataAdapter sorgt dann dafür, dass die Verbindung erneut aufgebaut wird und die geänderten Daten in die Originaldatenbank geschrieben werden. Ist die Aktualisierung beendet, wird die Verbindung automatisch geschlossen. Die Aktualisierung der Datenquelle ist ein komplexes Thema, auf das später noch genauer eingegangen wird.

Die Methode Fill wollen wir an dieser Stelle etwas näher betrachten. Fill ist vielfach überladen. Zwei Überladungen stellen wir hier vor:

public int Fill(DataTable)
public int Fill(DataSet)

Dem Aufruf wird im einfachsten Fall entweder ein DataTable- oder ein DataSet-Objekt übergeben. Beide Typen sind unabhängig vom .NET-Datenprovider und gehören zum Namespace System.Data. Ein DataTable-Objekt entspricht einer Tabelle in der Datenbank. Es hat die Spalten, die in der SELECT-Abfrage angegeben worden sind, und enthält die Datensätze, die das Ergebnis der SELECT-Abfrage bilden. Der Rückgabewert der Fill-Methode gibt Auskunft darüber, wie viele Datenzeilen dem DataSet oder der DataTable hinzugefügt worden sind.

Ein DataSet-Objekt können Sie sich als einen Container für mehrere DataTable-Objekte vorstellen. Im Beispiel oben hätten wir auch anstelle eines DataTable-Objekts ein DataSet füllen können. Allerdings würde der Code in der Schleife ein wenig anders aussehen:

[...]
DataSet ds = new DataSet();
da.Fill(ds);
for(int i=0; i < ds.Tables[0].Rows.Count; i++) {
DataRow row = ds.Tables[0].Rows[i];
Console.WriteLine("{0,1-35} {1}", row[0], row[1]);
}

Listing 33.3 Füllen eines DataSets

Nach dem Füllen einer DataTable oder eines DataSets gibt es keine Verbindung mehr zum SqlDataAdapter. Das bedeutet, dass weder der SqlDataAdapter eine Referenz auf das Objekt, das er gefüllt hat, besitzt noch das gefüllte Objekt weiß, von wem es gefüllt worden ist.


Rheinwerk Computing - Zum Seitenanfang

33.3.3 Öffnen und Schließen von VerbindungenZur nächsten ÜberschriftZur vorigen Überschrift

Kommen wir noch einmal auf das einführende Beispiel oben zurück. Mit

SqlDataAdapter da = new SqlDataAdapter(strSQL, con);

wird das SqlDataAdapter-Objekt erzeugt und dabei unter anderem die Referenz auf das Verbindungsobjekt con übergeben. Es fällt auf, dass die Open-Methode nicht aufgerufen wird, um die Abfrage zu übermitteln. Das ist auch nicht nötig, denn mit

da.Fill(tbl);

wird der DataAdapter die Verbindung selbstständig öffnen, die Ergebnisse abfragen und die Verbindung ebenso selbstständig schließen. Das steht ganz im Gegensatz zu den Execute-Methoden des SqlCommand-Objekts, die dieses Verhalten nicht zeigen und auf das explizite Öffnen der Verbindung angewiesen sind.

Sie können allerdings explizit eine Verbindung vor dem Aufruf von Fill mit Open öffnen. Der SqlDataAdapter wird das bemerken und weigert sich schlichtweg, die Verbindung von sich aus zu schließen, wenn die Resultate der Abfrage eingetroffen sind. Es liegt dann in Ihrer Verantwortung, die offene Verbindung zu schließen.

[...]
con.Open();
da.Fill(tbl);
con.Close();

Rheinwerk Computing - Zum Seitenanfang

33.3.4 Doppelter Aufruf der Fill-MethodeZur nächsten ÜberschriftZur vorigen Überschrift

Angenommen, Sie rufen zweimal hintereinander die Fill-Methode auf, ohne vor dem zweiten Aufruf das DataSet oder die DataTable zu leeren:

[...]
da.Fill(tbl);
da.Fill(tbl);

Die Idee, die dem doppelten Aufruf zugrunde liegt, könnte die Aktualisierung des DataSets sein. Allerdings werden nun die Datensätze in der Tabelle doppelt erscheinen. Mit dem ersten Aufruf der Fill-Methode wird das DataTable-Objekt erzeugt, und die Datensätze werden hineingeschrieben. Mit dem zweiten Aufruf werden die Datensätze einfach noch einmal aus der Datenquelle bezogen und in die schon vorhandene Tabelle kopiert.

Grund für dieses im ersten Moment etwas sonderbare Verhalten ist, dass die Primärschlüsselspalte der Originaltabelle nicht automatisch zur Primärschlüsselspalte der DataTable wird. Primärschlüssel dienen unter anderem zur Vermeidung von duplizierten Datensätzen und müssen in der Datenquelle festgelegt werden. Die DataTable übernimmt diese jedoch nicht.

Das DataTable-Objekt besitzt die Eigenschaft PrimaryKey. Wird diese gesetzt, wird der DataAdapter die doppelten Zeilen finden und die alten Werte verwerfen. Mehr Informationen darüber erhalten Sie in Kapitel 34.


Rheinwerk Computing - Zum Seitenanfang

33.3.5 Mehrere DataAdapter-Objekte aufrufenZur nächsten ÜberschriftZur vorigen Überschrift

Wird die Methode Fill hintereinander auf verschiedene DataAdapter aufgerufen, wird jeweils eine neue Verbindung benötigt. Daran ändert sich auch nichts, wenn allen Aufrufen die gleiche Verbindungszeichenfolge zugrunde liegt.

[...]
SqlDataAdapter daProducts = new SqlDataAdapter(strSQL1, con);
SqlDataAdapter daCategories = new SqlDataAdapter(strSQL2, con);
DataSet ds = new DataSet();
daProducts.Fill(ds);
[...]
daCategories.Fill(ds);

Listing 33.4 Das DataSet mit mehreren Tabellen füllen (nicht optimal)

Obwohl sich der Aufruf von Fill auf daCategories aus dem Verbindungspool bedient, darf das nicht darüber hinwegtäuschen, dass in diesem Codefragment unnötigerweise Leistungseinbußen in Kauf genommen werden müssen, weil in jedem Fall ein impliziter Open- bzw. Close-Aufruf auf die Verbindung erfolgt.

Wollen Sie sicherstellen, dass eine Verbindung von beiden SqlDataAdapter-Objekten gleichermaßen benutzt wird, müssen Sie die Steuerung selbst übernehmen und mit der Open-Methode die Verbindung vor dem ersten Füllen des DataSets bzw. der DataTable öffnen.

[...]
con.Open();
daProducts.Fill(dsProducts);
daCategories.Fill(dsCategories);
con.Close();

Listing 33.5 Das DataSet mit mehreren Tabellen füllen (optimal)


Rheinwerk Computing - Zum Seitenanfang

33.3.6 Die Spalten- und der Tabellenbezeichner einer DataTableZur nächsten ÜberschriftZur vorigen Überschrift

Intern bedient sich ein SqlDataAdapter des SqlDataReader-Objekts, um die Ergebnisse einer Abfrage abzurufen. Bevor die Resultate der Abfrage in der DataTable gespeichert werden, benutzt der SqlDataAdapter das SqlDataReader-Objekt, um sich elementare Schemainformationen zu besorgen. Dazu gehören die Spaltenbezeichner und die Datentypen. Aus diesem Grund können Sie über die Spaltenbezeichner auf bestimmte Spalten zugreifen, wenn Sie die Datenzeilen auswerten. Der SqlDataReader ist jedoch nicht in der Lage, den Tabellennamen zu liefern. Standardmäßig heißt die erste Tabelle Table, die zweite Table1, die dritte Table2 usw. Im nächsten Abschnitt werden wir uns in diesem Zusammenhang mit der TableMappingCollection des SqlDataAdapters beschäftigen. Anstatt einer TableMapping-Auflistung einen Eintrag hinzuzufügen, können Sie auch eine Überladung der Fill-Methode benutzen, der Sie im zweiten Parameter den Namen der Tabelle übergeben.

daProducts.Fill(ds, "Artikel");

Nun wird die im DataSet befindliche Tabelle unter dem Namen Artikel angesprochen, nicht mehr unter Table.


Rheinwerk Computing - Zum Seitenanfang

33.3.7 Paging mit der Fill-MethodeZur vorigen Überschrift

Eine interessante Überladung der Fill-Methode möchten wir Ihnen zum Abschluss noch vorstellen. Sie gestattet es, die DataTable mit nur einem Teil des Abfrageergebnisses zu füllen.

daProducts.Fill(ds, 0, 10, "Artikel");

Dieser Aufruf bewirkt, dass nur die ersten zehn Datenzeilen des nullbasierten Abfrageergebnisses im DataSet gespeichert werden. Tatsächlich werden dabei aber immer noch alle Datenzeilen von der Abfrage zurückgegeben. Der SqlDataAdapter, der sich bekanntlich intern des SqlDataReaders bedient, ruft dabei nur zehnmal die Read-Methode des SqlDataReaders auf.



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual C# 2012

Visual C# 2012
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: C/C++






 C/C++


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo





Copyright © Rheinwerk Verlag GmbH 2013
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