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 34 ADO.NET – Daten im lokalen Speicher
Pfeil 34.1 Allgemeines
Pfeil 34.2 Verwenden des DataSet-Objekts
Pfeil 34.2.1 Ein DataSet-Objekt erzeugen
Pfeil 34.2.2 Die Anatomie einer DataTable
Pfeil 34.2.3 Der Zugriff auf eine Tabelle im DataSet
Pfeil 34.2.4 Der Zugriff auf die Ergebnisliste
Pfeil 34.2.5 Dateninformationen in eine XML-Datei schreiben
Pfeil 34.3 Gültigkeitsprüfung im DataSet
Pfeil 34.3.1 Dem DataSet Schemainformationen übergeben
Pfeil 34.3.2 Eigenschaften einer DataColumn, die der Gültigkeitsprüfung dienen
Pfeil 34.3.3 Die Constraints-Klassen einer »DataTable«
Pfeil 34.3.4 Das Schema mit Programmcode erzeugen
Pfeil 34.3.5 Schemainformationen mit SqlDataAdapter abrufen
Pfeil 34.4 Änderungen in einer DataTable vornehmen
Pfeil 34.4.1 Editieren einer DataRow
Pfeil 34.4.2 Löschen einer Datenzeile
Pfeil 34.4.3 Eine neue Datenzeile hinzufügen
Pfeil 34.4.4 Der Sonderfall: Autoinkrementspalten
Pfeil 34.4.5 Was bei einer Änderung einer Datenzeile passiert
Pfeil 34.4.6 Manuelles Steuern der Eigenschaft »DataRowState«
Pfeil 34.5 Mit mehreren Tabellen arbeiten
Pfeil 34.5.1 Der Weg über JOIN-Abfragen
Pfeil 34.5.2 Mehrere Tabellen in einem DataSet
Pfeil 34.5.3 Eine DataRelation erzeugen
Pfeil 34.5.4 DataRelations und Einschränkungen
Pfeil 34.5.5 In Beziehung stehende Daten suchen
Pfeil 34.5.6 Ergänzung zum Speichern von Schemainformationen in einer XML-Schemadatei
Pfeil 34.6 Filtern und suchen in einer DataTable
Pfeil 34.6.1 Die Methode »Find«
Pfeil 34.6.2 Die Methode »Select«
Pfeil 34.7 Objekte vom Typ »DataView«
Pfeil 34.7.1 Einen »DataView« erzeugen
Pfeil 34.7.2 Auf die Datenzeilen in einem »DataView« zugreifen
Pfeil 34.7.3 Die Eigenschaft »Sort« und die Methode »Find«
Pfeil 34.7.4 Die Methode »FindRows«
Pfeil 34.7.5 Die Eigenschaft »RowFilter«
Pfeil 34.7.6 Die Eigenschaft »RowStateFilter«
Pfeil 34.7.7 Änderungen an einem »DataView«-Objekt
Pfeil 34.7.8 Aus einem »DataView« eine »DataTable« erzeugen

Rheinwerk Computing - Zum Seitenanfang

34.4 Änderungen in einer DataTable vornehmenZur nächsten Überschrift

Sehen wir uns nun an, wie wir einer DataTable eine neue DataRow hinzufügen und eine vorhandene DataRow löschen oder editieren können. Um einen wichtigen Punkt gleich vorwegzunehmen: Jegliche Änderung betrifft zunächst nur das DataSet. Die Originaldatenbank weiß davon nichts. Erst zu einem späteren Zeitpunkt werden alle Änderungen zur Datenbank übermittelt. Wir behandeln daher in diesem Abschnitt nur die lokalen Aktualisierungen. In Kapitel 35 werden wir uns der Aktualisierung der Originaldatenquelle zuwenden.


Rheinwerk Computing - Zum Seitenanfang

34.4.1 Editieren einer DataRowZur nächsten ÜberschriftZur vorigen Überschrift

Es gibt drei Möglichkeiten, eine Zeile zu aktualisieren. Im einfachsten Fall weisen Sie der betreffenden Spalte nur den neuen Inhalt zu:

ds.Tables[0].Rows[3]["ProductName"] = "Kirschkuchen";

Die Änderung wird sofort in die angegebene Spalte der entsprechenden Datenzeile geschrieben.

Die zweite Möglichkeit puffert die Änderung. Dazu wird vor Beginn der Änderung die Methode BeginEdit auf die zu ändernde Datenzeile aufgerufen und die Änderung mit EndEdit bestätigt. Sie können die eingeleitete Änderung auch zurücksetzen und anstelle von EndEdit die Methode CancelEdit aufrufen. Die Zeile wird dann in den Zustand zurückversetzt, den sie vor BeginEdit hatte.

DataRow row = ds.Tables[0].Rows[3];
row.BeginEdit();
row["ProductName"] = "Kirschkuchen";
row.EndEdit();
// Alternativ: row.cancelEdit();

Listing 34.6 Ändern einer Datenzeile

Die Pufferung der Änderung ist nicht der einzige Unterschied zwischen den beiden Aktualisierungsmöglichkeiten. Die DataTable verfügt über mehrere Ereignisse, die nur im Zusammenhang mit BeginEdit und EndEdit ausgelöst werden. Es handelt sich hierbei um

  • RowChanging
  • RowChanged
  • ColumnChanging
  • ColumnChanged

Diese Ereignisse spielen eine Rolle, wenn Änderungen an einer Datenzeile oder Spalte überprüft werden müssen. Die Ereignisse werden nicht ausgelöst, wenn Sie CancelEdit aufrufen. Wenn wir uns später dem Zurückschreiben der Änderungen in die Originaldatenbank zuwenden, werden wir noch einmal auf diese Ereignisse zurückkommen.

Die dritte Möglichkeit bietet uns die Eigenschaft ItemArray, die ein Object-Array beschreibt. Mit dieser Eigenschaft können Sie den Inhalt einer Datenzeile abrufen oder verändern. ItemArray arbeitet mit einem Array, in dem jedes Element einer Spalte entspricht. Mit einer Codezeile können Sie mehrere Spaltenwerte abrufen und editieren. Ist in einer Zeile nur eine Teilmenge der verfügbaren Werte zu modifizieren, verwenden Sie null, um anzuzeigen, dass der Wert dieser Spalte nicht geändert werden soll.

Im folgenden Codefragment werden drei Spalten der Tabelle Products abgefragt. In der ersten Datenzeile soll mit der Eigenschaft ItemArray der Produktbezeichner modifiziert werden. Weil der Schlüsselwert nicht geändert wird, muss an der ersten Position null in das Objekt-Array geschrieben werden.

SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "SELECT ProductID, ProductName, UnitPrice FROM Products";
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
DataRow row = ds.Tables[0].Rows[0];
row.ItemArray = new Object[] {null, "Kirschkuchen"};

Listing 34.7 Änderungen mit »ItemArray«

Den Spaltenwert auf NULL festlegen

Möchten Sie den Wert einer Spalte auf NULL setzen, verwenden Sie die Klasse DBNull, die sich im Namespace System befindet. Mit der Eigenschaft Value legen Sie den Wert einer Spalte in einer DataRow auf NULL fest.

DataRow row = ds.Tables[0].Rows[4];
row["UnitPrice"] = DBNull.Value;

Rheinwerk Computing - Zum Seitenanfang

34.4.2 Löschen einer DatenzeileZur nächsten ÜberschriftZur vorigen Überschrift

Das Löschen einer Datenzeile ist sehr einfach: Sie rufen hierzu die Methode Delete der DataRow auf, die gelöscht werden soll.

row.Delete();

Es ist falsch anzunehmen, dass die betreffende Datenzeile nun aus der DataTable entfernt wird. Sie ist immer noch vorhanden, allerdings kennzeichnet ADO.NET sie als gelöscht. Hintergrund der Markierung ist, dass das Löschen zunächst nur das aktuelle DataSet betrifft und zu einem späteren Zeitpunkt der Originaldatenbank mitgeteilt werden muss. Es wäre daher auch falsch, eine Datenzeile mit Remove oder RemoveAt aus der DataRowCollection der Tabelle zu entfernen, denn dann findet der Aktualisierungsprozess die Datenzeile nicht mehr.


Rheinwerk Computing - Zum Seitenanfang

34.4.3 Eine neue Datenzeile hinzufügenZur nächsten ÜberschriftZur vorigen Überschrift

Eine Datenzeile zu einer DataTable hinzuzufügen, ist auch nicht schwierig. Allerdings stellt die Klasse DataRow keinen öffentlichen Konstruktor zur Verfügung, denn woher sollte ein auf diese Weise konstruiertes DataRow-Objekt etwas von den Spalten wissen, durch die es beschrieben wird?

ADO.NET bietet Ihnen genauso wie zum Editieren einer Datenzeile drei Varianten an, um eine neue Datenzeile zu einer DataTable hinzuzufügen. Zunächst einmal sei die Methode NewRow der DataTable erwähnt. Eine so erzeugte neue Zeile enthält alle Informationen über die Spalten in der Tabelle. Werden im Schema keine Standardwerte vorgegeben, sind die Inhalte der Spalten auf NULL gesetzt. Haben Sie alle Einträge in der neuen Zeile vorgenommen, müssen Sie die neue Zeile der DataRowCollection anhängen, denn das leistet der Aufruf von NewRow nicht.

DataTable tbl = ds.Tables[0];
DataRow row = tbl.NewRow();
row["ProductName"] = "Erbsensuppe";
row["UnitPrice"] = 2;
row["SupplierID"] = 3;
[...]
tbl.Rows.Add(row);

Listing 34.8 Hinzufügen einer Datenzeile

Die zweite Möglichkeit, eine neue Datenzeile hinzuzufügen, bietet eine Überladung der Methode Add der DataRowCollection. Übergeben Sie dem Methodenaufruf die Spaltenwerte in der Reihenfolge, die der Reihenfolge der Spalten in der SELECT-Abfrage entspricht. Basierend auf der Auswahlabfrage

SELECT ProductName, Unitprice, UnitsInStock FROM Products

könnte eine neue Datenzeile wie folgt hinzugefügt werden:

ds.Tables[0].Rows.Add("Mehl", 20, 0);

Im Gegensatz zur Methode NewRow wird die neue Datenzeile automatisch der DataRowCollection hinzugefügt.

Die dritte Möglichkeit stellt die Methode LoadDataRow der DataTable dar. Diese Methode arbeitet ähnlich wie die zuvor gezeigte Add-Methode der DataRowCollection, verlangt aber die Angabe von zwei Parametern. Geben Sie im ersten Parameter ein Array von Werten an, dessen Elemente den Spalten in der Tabelle entsprechen. Tragen Sie im zweiten Parameter false ein. Hintergrund ist, dass die so gekennzeichnete Datenzeile als neue Datenzeile interpretiert wird. LoadDataRow eignet sich nämlich auch dazu, eine bestimmte Datenzeile zu suchen und zu modifizieren. Dann muss dem zweiten Parameter jedoch true übergeben werden.

ds.Tables[0].LoadDataRow(new object[] {"Mehl", 20, 0}, false);

Rheinwerk Computing - Zum Seitenanfang

34.4.4 Der Sonderfall: AutoinkrementspaltenZur nächsten ÜberschriftZur vorigen Überschrift

Viele Tabellen in Datenbanken beschreiben das Primärschlüsselfeld mit Autoinkrementwerten. Das ist vorteilhaft, weil eine zentrale Logik immer eindeutige Ganzzahlen erzeugt. Fügen wir jedoch eine neue Datenzeile zu einer DataTable hinzu, die ein solches Schlüsselfeld definiert, haben wir keine Verbindung zur Originaldatenbank. Mit anderen Worten: Wir kennen den neuen Wert des Schlüsselfeldes nicht. Den erfahren wir erst, wenn wir die Datenbank aktualisiert haben und eine entsprechende Abfrage starten.

ADO.NET unterstützt uns mit drei Eigenschaften der DataColumn, um auch diese scheinbare Problematik zu lösen:

  • AutoIncrement
  • AutoIncrementSeed
  • AutoIncrementStep

Um von ADO.NET in einer DataTable Autoinkrementwerte generieren zu lassen, muss die Eigenschaft AutoIncrement der betreffenden Spalte auf true gesetzt werden. Mit AutoIncrementSeed und AutoIncrementStep werden die von ADO.NET erzeugten Werte gesteuert. AutoIncrementSeed beschreibt dabei den Startwert der Autoinkrementspalte für die erste neu hinzugefügte Datenzeile. AutoIncrementStep gibt die Schrittweite an, mit der neue Schlüsselwerte generiert werden. Legen Sie für eine Autoinkrementspalte beispielsweise AutoIncrementSeed=1 und AutoIncrementStep=2 fest, lauten die Werte für die drei nachfolgend hinzugefügten Datenzeilen 1, 3 und 5.

Die Werte, die ADO.NET erzeugt, müssen Sie als Platzhalter verstehen. Sie werden später bei der Aktualisierung der Originaldatenbank nicht mit zurückgeschrieben. Die tatsächlichen Schlüsselwerte erzeugt die Datenbank selbst.

Doch welche Werte sollten Sie in der DataTable vergeben? Eigentlich müssen Sie nur sicherstellen, dass neue Schlüsselwerte nicht mit den Schlüsselwerten in Konflikt geraten, die bereits in der DataTable enthalten sind. Sie können auch davon ausgehen, dass negative Werte in der Datenbank nicht verwendet werden. Empfehlenswert ist daher, die beiden Eigenschaften AutoIncrementSeed und AutoIncrementStep auf jeweils –1 festzulegen. Zudem sollten diese Einstellungen erfolgen, ehe das DataSet mit den Daten gefüllt wird.

Sehen wir uns dazu nun ein Beispiel an.

// Beispiel: ..\Kapitel 34\AutoIncrementSample
class Program {
static void Main(string[] args) {
SqlConnection con = new SqlConnection();
con.ConnectionString = "...";
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "SELECT ProductID, ProductName FROM Products";
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(cmd);
// Schemainformationen abrufen
da.FillSchema(ds, SchemaType.Source);
// Festlegen, wie die neuen Schlüsselwerte erzeugt werden
ds.Tables[0].Columns[0].AutoIncrementSeed = -1;
ds.Tables[0].Columns[0].AutoIncrementStep = -1;
// DataSet füllen
da.Fill(ds);
// Neue Datenzeilen hinzufügen
DataRow row = ds.Tables[0].NewRow();
row["ProductName"] = "Kaffee";
ds.Tables[0].Rows.Add(row);
row = ds.Tables[0].NewRow();
row["ProductName"] = "Milch";
ds.Tables[0].Rows.Add(row);
row = ds.Tables[0].NewRow();
row["ProductName"] = "Zucker";
ds.Tables[0].Rows.Add(row);
// Ausgabe des DataSets
foreach (DataRow tempRow in ds.Tables[0].Rows)
Console.WriteLine("{0,-6}{1}",tempRow[0],tempRow[1]);
Console.ReadLine();
}
}

Listing 34.9 Hinzufügen von Datenzeilen mit einer Autoinkrementspalte

Damit der Code überschaubar bleibt, werden aus der Datenbank nur zwei Spalten der Tabelle Products abgefragt. Die Primärschlüsselspalte ProductID ist als Autoinkrementspalte definiert. Mit FillSchema werden die Metadaten der Tabelle bezogen. In der Praxis würde man diese Methode in einer Anwendung wohl aus den weiter oben angeführten Gründen nicht benutzen, aber für ein Beispielprogramm ist sie durchaus geeignet. Da FillSchema auch AutoIncrement=true für die Spalte ProductID setzt, muss diese Eigenschaft der DataColumn nicht mehr gesetzt werden.

Später werden der DataTable drei Datenzeilen hinzugefügt. Der temporäre Schlüsselwert der ersten ist auf –1 festgelegt. Alle weiteren neuen Schlüsselwerte werden mit der Schrittweite –1 generiert, so dass der Schlüsselwert der zweiten neuen Datenzeile –2 ist, der der dritten neuen Datenzeile –3. Beachten Sie, dass die Autoinkrementeigenschaften vor dem Füllen des DataSets gesetzt werden müssen. Ansonsten wirken sich die Eigenschaftswerte nicht auf die Autoinkrementwerte aus, die die DataTable generiert.

Zum Abschluss unserer Betrachtungen zu den Autoinkrementwerten noch eine Anmerkung: Vergessen Sie nicht, dass die generierten Schlüsselwerte nur Platzhalter innerhalb der DataTable darstellen. Erst nach der Übermittlung zur Originaldatenbank werden die tatsächlichen und endgültigen Schlüsselwerte von der Datenbank erzeugt. Sie sollten daher vermeiden, die temporären Schlüsselwerte dem Anwender anzuzeigen. Es könnte unabsehbare Folgen haben, wenn der Anwender sich eine ADO.NET-Schlüsselnummer notiert, die später nach der Aktualisierung nicht mehr existiert.


Rheinwerk Computing - Zum Seitenanfang

34.4.5 Was bei einer Änderung einer Datenzeile passiertZur nächsten ÜberschriftZur vorigen Überschrift

Die Eigenschaft »RowState«

Ein DataSet ist im lokalen Cache der Anwendung abgelegt. Während des Löschens, Änderns und Hinzufügens von Datenzeilen besteht zu der Originaldatenbank keine Verbindung. Wenn der Benutzer die geänderten Daten später an die Datenbank übermitteln möchte, muss sich das DataSet daran erinnern können, welche Zeilen von einer Änderung betroffen sind, und natürlich auch, welcher Natur diese Änderung ist. Haben Sie beispielsweise eine Datenzeile gelöscht, muss für die betreffende Datenzeile ein DELETE-SQL-Statement zur Datenbank geschickt werden, das das Löschen in der Originaltabelle bewirkt. Haben Sie eine Datenzeile geändert, bedarf es eines passend formulierten UPDATE-Statements. Wie die Aktualisierungsabfragen erzeugt werden, sei an dieser Stelle noch nicht erläutert. Das werden wir uns im Detail später noch ansehen. Aber Sie sollten an dieser Stelle erkennen, wie wichtig es ist, dass jede Datenzeile ihren eigenen Aktualisierungszustand beschreiben kann.

ADO.NET speichert die notwendigen Zustandsinformationen in der Eigenschaft RowState jeder Datenzeile. Die Eigenschaft wird durch die Enumeration DataRowState beschrieben, wie in Tabelle 34.3 aufgelistet.

Tabelle 34.3 Mitglieder der Enumeration DataRowState

Member Beschreibung

Added

Die Zeile wurde einer DataRowCollection hinzugefügt.

Deleted

Die Zeile wurde mit der Delete-Methode der DataRow gelöscht.

Detached

Die Zeile wurde erstellt, ist jedoch nicht Teil einer DataRowCollection. Eine DataRow befindet sich in diesem Zustand, wenn sie unmittelbar nach ihrer Erstellung noch keiner Auflistung hinzugefügt wurde oder wenn sie aus einer Auflistung entfernt wurde.

Modified

Die Zeile wurde geändert.

Unchanged

Die Zeile wurde nicht geändert.

Der ursprüngliche und der aktualisierte Inhalt einer Datenzeile

Sie wissen nun, dass eine Datenzeile beschreibt, ob und wie sie modifiziert wurde. Um später die Änderung zur Datenbank zu übermitteln, reicht das aber noch nicht aus: Es fehlen noch dringend notwendige Informationen. Stellen Sie sich dazu nur vor, Sie würden den Artikelbezeichner einer Datenzeile der Tabelle Products ändern und die Änderung mit einem UPDATE-Statement der Datenbank mitteilen. Das SQL-Statement könnte wie folgt lauten:

UPDATE Products
SET ProductName = @Param1
WHERE ProductID = @Param2 AND ProductName = @Param3

Im Parameter @Param1 wird der geänderte, also neue Wert übermittelt, in @Param2 der Schlüsselwert der Datenzeile und in @Param3 der ursprüngliche Wert der Spalte ProductID. Setzen Sie ein solches Statement ab, darf natürlich zwischen dem Abrufen der Dateninformationen und der Aktualisierung kein zweiter Benutzer den Produktnamen geändert haben. Die Folge wäre eine Konfliktsituation, weil die anstehende Änderung nicht in die Datenbank geschrieben werden kann. Dieser (scheinbaren) Problematik wollen wir an dieser Stelle noch nicht weiter nachgehen.

Sie sollten erkennen: Um das UPDATE-Statement erfolgreich absetzen zu können, bedarf es nicht nur der geänderten Werte, sondern auch des Originalwertes, um die Datenzeile in der Datenbank zu identifizieren. Für diesen Zweck ist der Indexer einer DataRow überladen. Anstatt mit

row["Productname"]

den aktuellen, also möglicherweise geänderten Wert der Spalte ProductName abzurufen, können Sie auch mit

row["Productname", DataRowVersion.Original]

auf den von der Datenbank bezogenen Originalwert zurückgreifen.

DataRowVersion ist eine Aufzählung, mit der die gewünschte Version der betreffenden Spalte in der Datenzeile angegeben werden kann.

Tabelle 34.4 Die Werte der Enumeration DataRowVersion

Member Beschreibung

Current

Die Zeile enthält aktuelle Werte.

Default

Die Zeile enthält einen vorgeschlagenen Wert.

Original

Die Standardversion der Zeile, dem aktuellen DataRowState entsprechend.

Proposed

Die Zeile enthält ihre ursprünglichen Werte.

Sie können sich jetzt sicher vorstellen, dass es von jeder DataRow immer zwei Versionen gibt: Zunächst einmal DataRowVersion.Original für die Werte, die aus der Datenbank bezogen worden sind, und DataRowVersion.Current für die aktuellen und möglicherweise geänderten Werte. Jetzt wird auch verständlich, warum es nach der Einleitung einer Änderung mit BeginEdit mittels CancelEdit möglich ist, den ursprünglichen Zustand einer DataRow wiederherzustellen. Rufen Sie mit

row["ProductName"]

den Inhalt einer Spalte ab, wird immer DataRowVersion.Current ausgewertet. Das ist wichtig zu wissen, denn sollten Sie die DataRowCollection in einer Schleife durchlaufen, innerhalb deren zum Beispiel auf Spalten aller geänderten Zeilen zugegriffen wird, dürfen Sie von einer gelöschten Zeile nicht DataRowVersion.Current abrufen. Sie können aber sehr wohl DataRowVersion.Original auswerten, weil eine als gelöscht markierte Datenzeile nicht aus der DataRowCollection entfernt wird.

Das nächste Beispiel zeigt Ihnen die prinzipielle Vorgehensweise: Nachdem das DataSet aus der Artikeltabelle mit Daten gefüllt ist, wird zuerst ein weiterer Datensatz hinzugefügt. Anschließend wird in der Tabelle nach einem bestimmten Artikel gesucht (Tofu). Hierzu wird die Methode Select der DataTable aufgerufen, die mehrere Überladungen aufweist. Benutzt wird in diesem Beispiel die einfach parametrisierte Version, der ein Suchkriterium als Zeichenfolge übergeben wird. Die Zeichenfolge entspricht der WHERE-Klausel in einer SELECT-Abfrage ohne die Angabe von WHERE. Zum Schluss wird auch noch die fünfte Datenzeile aus der Liste »gelöscht«.

An der Konsole werden abschließend nur die Datenzeilen angezeigt, die in irgendeiner Form gegenüber dem Original eine Änderung erfahren haben.

// Beispiel: ..\Kapitel 34\AusgabeModifizierterDaten
class Program {
static void Main(string[] args) {
SqlConnection con = new SqlConnection();
con.ConnectionString = "...";
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "SELECT ProductID, ProductName, UnitsInStock " +
"FROM Products";
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.FillSchema(ds, SchemaType.Source);
ds.Tables[0].Columns["ProductID"].AutoIncrementSeed = -1;
ds.Tables[0].Columns["ProductID"].AutoIncrementStep = -1;
da.Fill(ds);
// Neue Datenzeile hinzufügen
DataRow newRow = ds.Tables[0].NewRow();
newRow["ProductName"] = "Camembert";
newRow["UnitsInStock"] = 100;
ds.Tables[0].Rows.Add(newRow);
// Datenzeile ändern
DataRow[] editRow = ds.Tables[0].Select("ProductName='Tofu'");
if (editRow.Length == 1) {
editRow[0].BeginEdit();
editRow[0]["UnitsInStock"] = 1000;
editRow[0].EndEdit();
}
else
Console.WriteLine("Datenzeile 'Tofu' nicht gefunden.");
// Datenzeile löschen
ds.Tables[0].Rows[4].Delete();
// Ausgabe
foreach (DataRow tempRow in ds.Tables[0].Rows) {
if (tempRow.RowState == DataRowState.Added)
Console.WriteLine("Neue Datenzeile: {0}", tempRow["Productname"]);
else if (tempRow.RowState == DataRowState.Modified) {
Console.WriteLine("Modifiziert: {0}", tempRow["Productname"]);
Console.WriteLine("Alter Wert: {0}",
tempRow["UnitsInStock", DataRowVersion.Original]);
Console.WriteLine("Neuer Wert: {0}", tempRow["UnitsInStock"]);
}
else if (tempRow.RowState == DataRowState.Deleted)
Console.WriteLine("Gelöscht: {0}",
tempRow["ProductName", DataRowVersion.Original]);
else
continue;
Console.WriteLine(new string('-', 40));
}
Console.ReadLine();
}
}

Listing 34.10 Anzeige modifizierter Datenzeilen


Rheinwerk Computing - Zum Seitenanfang

34.4.6 Manuelles Steuern der Eigenschaft »DataRowState«Zur nächsten ÜberschriftZur vorigen Überschrift

Die Eigenschaft RowState ist für jede Datenzeile nach dem Füllen des DataSets auf Unchanged gesetzt. Je nachdem, ob Sie eine Datenzeile ändern, löschen oder hinzufügen, wird ihr Zustand automatisch auf Modified, Deleted oder Added gesetzt.

Mit zwei Methoden können Sie den RowState per Code beeinflussen: AcceptChanges und RejectChanges. Es handelt sich hierbei um Methoden, die Sie auf dem DataSet, der DataTable oder einer bestimmten DataRow aufrufen können.

Die Methode »AcceptChanges«

AcceptChanges setzt den RowState einer Datenzeile von Added oder Modified auf Unchanged. Dabei wird der Inhalt von DataRowVersion.Original durch den von DataRowVersion.Current beschriebenen Inhalt ersetzt.

Trifft die Methode auf eine gelöschte Datenzeile, wird die Datenzeile aus der DataRowCollection entfernt und RowState auf DataRowState.Detached gesetzt. Rufen Sie AcceptChanges auf die Referenz des DataSets auf, wird mit allen Datenzeilenänderungen in sämtlichen Tabellen so verfahren. Der Aufruf auf eine bestimmte Tabelle im DataSet wirkt sich dementsprechend nur auf die betreffenden Datenzeilen der Tabelle aus. Analog können Sie auch den Zustand einer bestimmten Datenzeile ändern.

Die Methode »RejectChanges«

Mit RejectChanges verwerfen Sie alle Änderungen. Die Methode setzt die aktuellen Werte der DataRow auf ihre ursprünglichen Werte zurück. Dabei werden die in der DataRow enthaltenen Änderungen verworfen, also:

DataRowVersion.Current = DataRowVersion.Original

Der RowState hängt nach dem Aufruf von RejectChanges vom anfänglichen RowState ab. Der Zustand Deleted oder Modified wird zu Unchanged, eine hinzugefügte Datenzeile wird zu Detached.

Die Methoden »SetAdded« und »SetModified«

SetAdded ändert den Zustand einer Datenzeile in Added und kann nur für eine DataRow aufgerufen werden, deren RowState den Wert Unchanged oder Added hat. Ist der Ausgangszustand ein anderer, wird die Ausnahme InvalidOperationException ausgelöst.

Dementsprechend ändert SetModified den Zustand in Modified. Der Einsatz dieser Methode beschränkt sich auf Datenzeilen, deren Ausgangszustand Unchanged ist. Ansonsten wird ebenfalls die eben erwähnte Ausnahme ausgelöst.



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