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


Galileo Computing - Zum Seitenanfang

26.3 Änderungen in einer DataTable vornehmen Zur nächsten ÜberschriftZur vorigen Ü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. Im Kapitel 27, »ADO.NET – Aktualisieren der Datenbank«, werden wir uns der Aktualisierung der Originaldatenquelle zuwenden.


Galileo Computing - Zum Seitenanfang

26.3.1 Editieren einer DataRow Zur 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 der zu ändernden 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();

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"};

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;


Galileo Computing - Zum Seitenanfang

26.3.2 Datenzeile löschen Zur 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. Der Grund für die 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.


Galileo Computing - Zum Seitenanfang

26.3.3 Neue Datenzeile hinzufügen Zur 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);

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. Der Grund dafür 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);


Galileo Computing - Zum Seitenanfang

26.3.4 Der Sonderfall: Autoinkrementspalten Zur 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 26\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);
    // Schema-Informationen 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();
  }
}

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, sodass 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 zu unabsehbaren Folgen führen, wenn der Anwender sich eine ADO.NET-Schlüsselnummer notiert, die später nach der Aktualisierung nicht mehr existiert.


Galileo Computing - Zum Seitenanfang

26.3.5 Was passiert bei der Änderung einer Datenzeile? Zur 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 daran, 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, brauchen Sie noch ein passend formuliertes UPDATE-Statement. Wie die Aktualisierungsabfragen erzeugt werden, erläutere ich an dieser Stelle noch nicht. 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 26.3 aufgelistet.


Tabelle 26.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.


Ursprünglicher und aktualisierter 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. Wenn Sie ein solches Statement absetzen, 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 Folgendes erkennen: Um das UPDATE-Statement erfolgreich absetzen zu können, brauchen Sie außer den geänderten Werten auch den Originalwert, 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 26.4 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 unter DataRowVersion.Current 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 der 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 26\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();
  }
}


Galileo Computing - Zum Seitenanfang

26.3.6 Manuelles Steuern der Eigenschaft »DataRowState« topZur 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.



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