Zurückspeichern von Daten in die Datenbank in .NET Framework-Anwendungen

Hinweis

Datasets und verwandte Klassen sind ältere .NET-Technologien aus den frühen 2000er Jahren, die es Anwendungen ermöglichen, mit Daten im Arbeitsspeicher zu arbeiten, während die Anwendungen von der Datenbank getrennt sind. Sie sind besonders nützlich für Anwendungen, die es Benutzern ermöglichen, Daten zu ändern und die Änderungen wieder in der Datenbank zu speichern. Obwohl sich Datasets als sehr erfolgreiche Technologie erwiesen haben, empfehlen wir, dass neue .NET-Anwendungen Entity Framework Core verwenden. Entity Framework bietet eine natürlichere Möglichkeit, mit tabellarischen Daten als Objektmodelle zu arbeiten, und verfügt über eine einfachere Programmierschnittstelle.

Das Dataset ist eine In-Memory-Kopie der Daten. Wenn Sie diese Daten ändern, empfiehlt es sich, die Änderungen wieder in der Datenbank zu speichern. Dazu stehen Ihnen drei Möglichkeiten zur Verfügung:

  • Aufruf einer der Update-Methoden für einen TableAdapter.

  • Aufruf einer der DBDirect-Methoden für den TableAdapter.

  • Aufruf der UpdateAll-Methode für den TableAdapterManager. Diese wird von Visual Studio für Sie generiert, wenn das Dataset Tabellen enthält, die mit anderen Tabellen im Dataset verknüpft sind.

Wenn Sie Tabellen eines Datasets an Steuerelemente in einem Windows-Formular oder einer XAML-Seite binden, übernimmt die Datenbindungsarchitektur die gesamte Arbeit für Sie.

Wenn Sie mit TableAdapters vertraut sind, können Sie direkt zu einem dieser Themen wechseln:

Thema BESCHREIBUNG
Einfügen neuer Datensätze in eine Datenbank Durchführen von Aktualisierungen und Einfügungen mit TableAdapters oder Command-Objekten
Aktualisieren von Daten mit einem TableAdapter Durchführen von Aktualisierungen mit TableAdapters
Hierarchische Aktualisierung Durchführen von Aktualisierungen aus einem Dataset mit zwei oder mehr zugehörigen Tabellen
Behandeln einer Parallelitätsausnahme Behandeln von Ausnahmen durch den Versuch zweier Benutzer, gleichzeitig dieselben Daten in einer Datenbank zu ändern
Vorgehensweise: Speichern von Daten mithilfe von Transaktionen Speichern von Daten in einer Transaktion mit dem System.Transactions-Namespace und einem TransactionScope-Objekt
Speichern von Daten in einer Transaktion Exemplarische Vorgehensweise: Erstellung einer Windows Forms-Anwendung zur Demonstration des Speicherns von Daten in einer Datenbank innerhalb einer Transaktion
Speichern von Daten in einer Datenbank (mehrere Tabellen) Bearbeiten von Datensätzen und Rückspeichern von Änderungen in mehreren Tabellen in der Datenbank
Speichern von Daten aus einem Objekt in einer Datenbank Übergeben von Daten aus einem nicht im Dataset enthaltenen Objekt an eine Datenbank mit einer TableAdapter-DbDirect-Methode
Speichern von Daten mit den TableAdapter-DBDirect-Methoden Verwenden des TableAdapters zum direkten Senden von SQL-Abfragen an die Datenbank
Speichern eines Datasets als XML Speichern eines Datasets in einem XML-Dokument

Zweistufige Aktualisierungen

Die Aktualisierung einer Datenquelle erfolgt in zwei Schritten. Der erste Schritt besteht darin, das Dataset mit neuen, geänderten oder gelöschten Datensätzen zu aktualisieren. Wenn Ihre Anwendung diese Änderungen nie an die Datenquelle zurücksendet, ist die Aktualisierung abgeschlossen.

Wenn Sie die Änderungen an die Datenbank zurücksenden, ist ein zweiter Schritt erforderlich. Wenn Sie keine datengebundenen Steuerelemente verwenden, müssen Sie die Update-Methode des zum Auffüllen des Datasets verwendeten TableAdapters (oder Datenadapters) manuell aufrufen. Sie können jedoch auch verschiedene Adapter verwenden, z. B. um Daten von einer Datenquelle in eine andere zu verschieben oder um mehrere Datenquellen zu aktualisieren. Wenn Sie keine Datenbindung verwenden und Änderungen für zugehörige Tabellen speichern, müssen Sie manuell eine Variable der automatisch generierten TableAdapterManager-Klasse instanziieren und dann ihre UpdateAll-Methode aufrufen.

Konzeptgrafik zu Datasetaktualisierungen

Ein Dataset enthält Sammlungen von Tabellen, die wiederum eine Sammlung von Zeilen enthalten. Wenn Sie eine zugrunde liegende Datenquelle später aktualisieren möchten, müssen Sie beim Hinzufügen oder Entfernen von Zeilen die Methoden der Eigenschaft DataTable.DataRowCollection verwenden. Diese Methoden übernehmen die Änderungsverfolgung, die zum Aktualisieren der Datenquelle erforderlich ist. Wenn Sie die RemoveAt-Sammlung für die Eigenschaft „Rows“ aufrufen, wird der Löschvorgang nicht an die Datenbank zurückgemeldet.

Zusammenführen von Datasets

Sie können den Inhalt eines Datasets aktualisieren, indem Sie es mit einem anderen Dataset zusammenführen. Dabei wird der Inhalt eines Quelldatasets in das aufrufende Dataset (das sogenannte Zieldataset) kopiert. Beim Zusammenführen von Datasets werden neue Datensätze aus dem Quell-Dataset in das Ziel-Dataset eingefügt. Darüber hinaus werden dem Ziel-Dataset zusätzliche Spalten aus dem Quell-Dataset hinzugefügt. Das Zusammenführen von Datasets ist nützlich, wenn Sie über ein lokales Dataset verfügen und ein zweites Dataset aus einer anderen Anwendung erhalten. Es ist auch nützlich, wenn Sie ein zweites Dataset von einer Komponente wie einem XML-Webdienst erhalten, oder wenn Sie Daten aus mehreren Datasets integrieren müssen.

Beim Zusammenführen von Datasets können Sie ein boolesches Argument (preserveChanges) übergeben, das der Merge-Methode mitteilt, ob vorhandene Änderungen im Zieldataset beibehalten werden sollen. Da Datasets mehrere Datensatzversionen verwalten, darf nicht außer Acht gelassen werden, dass auch mehrere Datensatzversionen zusammengeführt werden. Die folgende Tabelle zeigt, wie ein Datensatz in zwei Datasets zusammengeführt wird:

DataRowVersion Zieldataset Quelldataset
Ursprünglich James Wilson James C. Wilson
Aktuell Jim Wilson James C. Wilson

Durch einen Aufruf der Merge-Methode für die oben dargestellte Tabelle mit preserveChanges=false targetDataset.Merge(sourceDataset) erhalten Sie die folgenden Daten:

DataRowVersion Zieldataset Quelldataset
Ursprünglich James C. Wilson James C. Wilson
Aktuell James C. Wilson James C. Wilson

Durch einen Aufruf der Merge-Methode mit preserveChanges = true targetDataset.Merge(sourceDataset, true) erhalten Sie die folgenden Daten:

DataRowVersion Zieldataset Quelldataset
Ursprünglich James C. Wilson James C. Wilson
Aktuell Jim Wilson James C. Wilson

Achtung

Wenn im preserveChanges = true-Szenario die RejectChanges-Methode für einen Datensatz im Zieldataset aufgerufen wird, werden die Daten auf die ursprünglichen Daten im Quelldataset zurückgesetzt. Wenn Sie also versuchen, die ursprüngliche Datenquelle mit dem Zieldataset zu aktualisieren, wird die ursprüngliche zu aktualisierende Zeile möglicherweise nicht gefunden. Sie können eine Parallelitätsverletzung vermeiden, indem Sie ein anderes Dataset mit den aktualisierten Datensätzen auffüllen und anschließend einen Merge ausführen. (Eine Parallelitätsverletzung liegt vor, wenn ein anderer Benutzer einen Datensatz in der Datenquelle ändert, nachdem das Dataset aufgefüllt wurde.)

Einschränkungen bei der Aktualisierung

Um Änderungen an einer bestehenden Datenzeile vorzunehmen, fügen Sie einzelnen Spalten Daten hinzu oder aktualisieren sie. Wenn das Dataset Einschränkungen enthält (z. B. Fremdschlüssel oder Non-Nullable-Einschränkungen), kann der Datensatz beim Aktualisieren vorübergehend in einen Fehlerzustand wechseln. Dies bedeutet, dass sich der Datensatz in einem Fehlerzustand befinden kann, nachdem die Aktualisierung einer Spalte abgeschlossen wurde, aber bevor zur nächsten Spalte übergegangen wird.

Um vorzeitige Verletzungen dieser Einschränkungen zu vermeiden, können Sie sie vorübergehend außer Kraft setzen. Dies erfüllt zweierlei Zwecke:

  • Es verhindert die Auslösung eines Fehlers, nachdem Sie die Aktualisierung einer Spalte abgeschlossen, aber noch nicht mit der Aktualisierung einer anderen Spalte begonnen haben.

  • Bestimmte (häufig für Validierungen verwendete) Aktualisierungsereignisse werden nicht ausgelöst.

Hinweis

In Windows Forms wird die Überprüfung von Einschränkungen durch die in das Datenraster integrierte Datenbindungsarchitektur unterbunden, bis der Fokus auf eine andere Zeile übergeht. Daher müssen die Methoden BeginEdit, EndEdit oder CancelEdit nicht explizit aufgerufen werden.

Beim Aufruf der Merge-Methode für ein Dataset werden Einschränkungen automatisch deaktiviert. Wenn nach einer erfolgreichen Zusammenführung weiterhin Einschränkungen für das Dataset bestehen, die nicht deaktiviert werden können, wird eine ConstraintException ausgelöst. In einer solchen Situation ist die EnforceConstraints-Eigenschaft auf false, festgelegt, und alle Einschränkungsverletzungen müssen vor dem Zurücksetzen der EnforceConstraints-Eigenschaft auf true aufgelöst werden.

Nachdem eine Aktualisierung abgeschlossen wurde, können Sie die Überprüfung von Einschränkungen wieder aktivieren, wodurch auch Aktualisierungsereignisse wieder aktiviert und ausgelöst werden.

Weitere Informationen über das Anhalten von Ereignissen finden Sie unter Deaktivieren von Einschränkungen beim Auffüllen von Datasets.

Fehler bei der Datasetaktualisierung

Bei der Aktualisierung von Datensätzen in einen Dataset können Fehler auftreten. Sie könnten z. B. versehentlich Daten in eine Spalte schreiben, die den falschen Typ aufweisen, zu lang sind oder ein anderes Integritätsproblem verursachen. Oder Sie nutzen möglicherweise anwendungsspezifische Validierungsprüfungen, die in jeder Phase eines Aktualisierungsereignisses benutzerdefinierte Fehler auslösen können. Weitere Informationen finden Sie unter Überprüfen von Daten in Datasets.

Verwalten von Informationen über Änderungen

Informationen zu Änderungen in einem Dataset werden in zweifacher Weise verwaltet: durch Zeilenkennzeichnungen, die auf eine Änderung hinweisen (RowState), und durch die Speicherung mehrerer Kopien eines Datensatzes (DataRowVersion). Mithilfe dieser Informationen können die geänderten Daten im Dataset vom Prozess ermittelt und die entsprechenden Aktualisierungen an die Datenquelle gesendet werden.

RowState-Eigenschaft

Die RowState-Eigenschaft eines DataRow-Objekts stellt einen Wert dar, der Informationen zum Status einer bestimmten Datenzeile bereitstellt.

In der folgenden Tabelle sind die möglichen Werte für die DataRowState-Enumeration aufgeführt:

DataRowState-Wert BESCHREIBUNG
Added Die Zeile wurde einer DataRowCollection als Element hinzugefügt. (Eine Zeile in diesem Zustand verfügt über keine entsprechende Originalversion, da sie beim Aufruf der letzten AcceptChanges-Methode noch nicht vorhanden war).
Deleted Die Zeile wurde mit Delete eines DataRow-Objekts gelöscht.
Detached Die Zeile wurde zwar erstellt, gehört aber keiner DataRowCollection an. Ein DataRow-Objekt befindet sich unmittelbar nach seiner Erstellung, vor dem Hinzufügen zu einer Sammlung und nach dem Entfernen aus einer Sammlung in diesem Zustand.
Modified Ein Spaltenwert in der Zeile wurde in beliebiger Weise geändert.
Unchanged Die Zeile wurde seit dem letzten Aufruf von AcceptChanges nicht geändert.

DataRowVersion-Enumeration

In Datasets werden mehrere Datensatzversionen verwaltet. Die DataRowVersion-Felder werden verwendet, wenn Sie den in einer DataRow gefundenen Wert mithilfe der Item[]-Eigenschaft oder der GetChildRows-Methode des DataRow-Objekts abrufen.

In der folgenden Tabelle sind die möglichen Werte für die DataRowVersion-Enumeration aufgeführt:

DataRowVersion-Wert BESCHREIBUNG
Current Die aktuelle Version eines Datensatzes enthält alle Änderungen, die seit dem letzten Aufruf von AcceptChanges am Datensatz vorgenommen wurden. Falls die Zeile gelöscht wurde, ist keine aktuelle Version vorhanden.
Default Der Standardwert eines Datensatzes, wie er durch das Dataset-Schema oder die Datenquelle definiert wurde.
Original Die ursprüngliche Version eines Datensatzes ist eine Kopie des Datensatzes zu dem Zeitpunkt, zu dem zuletzt ein Commit für Dataset-Änderungen ausgeführt wurde. Praktisch entspricht dies meist der Version eines Datensatzes, die aus einer Datenquelle gelesen wurde.
Proposed Die vorläufige Version eines Datensatzes ist während der laufenden Aktualisierung vorübergehend verfügbar, d.h. nach dem Aufruf der BeginEdit-Methode und vor dem Aufruf der EndEdit-Methode. Auf die vorläufige Version eines Datensatzes greifen Sie i. d. R. in einem Ereignishandler zu, z. B. RowChanging. Durch den Aufruf der CancelEdit-Methode werden die Änderungen rückgängig gemacht und die vorläufige Version aus der Datenzeile gelöscht.

Die ursprüngliche und die aktuelle Version sind hilfreich, wenn Aktualisierungsinformationen an eine Datenquelle übertragen werden. Wenn eine Aktualisierung an die Datenquelle gesendet wird, befinden sich die neuen Informationen für die Datenbank i. d. R. in der aktuellen Version des Datensatzes. Anhand von Informationen aus der ursprünglichen Version wird der zu aktualisierende Datensatz gesucht.

Wenn beispielsweise der Primärschlüssel eines Datensatzes geändert wird, müssen Sie den richtigen Datensatz in der Datenquelle ermitteln können, um die Änderungen zu aktualisieren. Wenn keine ursprüngliche Version vorhanden ist, wird der Datensatz höchstwahrscheinlich an die Datenquelle angefügt. Daraus resultiert dann nicht nur ein ungewollter zusätzlicher, sondern auch ungenauer und nicht mehr aktueller Datensatz. Die beiden Versionen werden auch in der Parallelitätssteuerung verwendet. Sie können die ursprüngliche Version mit einem Datensatz in der Datenquelle vergleichen, um festzustellen, ob der Datensatz geändert wurde, seitdem er zuletzt in das Dataset geladen wurde.

Die vorläufige Version ist von Nutzen, wenn Sie eine Validierung durchführen müssen, bevor die Änderungen am Dataset endgültig bestätigt werden.

Selbst wenn Datensätze geändert wurden, ist nicht immer eine ursprüngliche oder aktuelle Version der betreffenden Zeile verfügbar. Wenn Sie eine neue Zeile in die Tabelle einfügen, existiert keine ursprüngliche, sondern nur eine aktuelle Version. Auch wenn Sie eine Zeile durch den Aufruf der tabellenspezifischen Delete-Methode löschen, ist eine ursprüngliche, aber keine aktuelle Version vorhanden.

Durch Abfrage der HasVersion-Methode der Datenzeile können Sie überprüfen, ob eine bestimmte Version eines Datensatzes vorhanden ist. Um auf eine der verschiedenen Datensatzversionen zuzugreifen, übergeben Sie einen DataRowVersion-Enumerationswert als optionales Argument, wenn Sie den Wert einer Spalte anfordern.

Abrufen geänderter Datensätze

Es ist üblich, nicht jeden Datensatz in einem Dataset zu aktualisieren. Beispielsweise kann ein Benutzer mit einem DataGridView-Steuerelement von Windows Forms arbeiten, durch das zahlreiche Datensätze angezeigt werden. Der Benutzer aktualisiert jedoch vielleicht nur einige wenige Datensätze, löscht einen Datensatz und fügt einen neuen ein. Datasets und Datentabellen bieten eine Methode (GetChanges), mit deren Hilfe ausschließlich die geänderten Zeilen zurückgegeben werden können.

Sie können Teilmengen der geänderten Datensätze erstellen, indem Sie entweder die GetChanges-Methode der Datentabelle (GetChanges) oder des Datasets selbst (GetChanges) verwenden. Wenn Sie die Methode für die Datentabelle aufrufen, wird eine Kopie der Tabelle zurückgegeben, die lediglich die geänderten Datensätze enthält. Ähnlich verhält es sich, wenn Sie die Methode für den Dataset aufrufen: Sie erhalten ein neues Dataset, das nur geänderte Datensätze enthält.

GetChanges allein gibt alle geänderten Datensätze zurück. Im Gegensatz dazu können Sie durch Übergeben des gewünschten DataRowState als Parameter an die GetChanges-Methode die abzurufende Teilmenge der geänderten Datensätze angeben: neu hinzugefügte Datensätze, zum Löschen markierte Datensätze, abgetrennte Datensätze oder geänderte Datensätze.

Eine Teilmenge der geänderten Datensätze abzurufen, ist nützlich, wenn Datensätze zur Verarbeitung an eine andere Komponente gesendet werden sollen. Anstatt das gesamte Dataset zu übertragen, können Sie die Kommunikation mit der anderen Komponente gering halten, indem Sie lediglich die Datensätze abrufen, die von der Komponente benötigt werden.

Committen von Änderungen im Dataset

Während Sie Änderungen im Dataset vornehmen, wird die RowState-Eigenschaft der geänderten Zeilen festgelegt. Die ursprünglichen und aktuellen Datensatzversionen werden von der RowVersion-Eigenschaft eingerichtet, verwaltet und verfügbar gemacht. Die in den Eigenschaften dieser geänderten Zeilen gespeicherten Metadaten werden benötigt, um die richtigen Aktualisierungen an die Datenquelle zu senden.

Wenn die Änderungen den aktuellen Zustand der Datenquelle widerspiegeln, müssen diese Informationen nicht länger beibehalten werden. Es gibt in der Regel zwei Situationen, in denen das Dataset und seine Quelle synchron sind:

  • Unmittelbar nach dem Laden von Informationen in das Dataset, z. B., wenn Sie Daten aus der Quelle einlesen.

  • Nach dem Senden von Änderungen aus dem Dataset an die Datenquelle (aber nicht vorher, da Sie ansonsten die Änderungsinformationen verlieren, die zum Senden von Änderungen an die Datenbank benötigt werden).

Sie können für die ausstehenden Änderungen im Dataset ein Commit ausführen, indem Sie die AcceptChanges-Methode aufrufen. Normalerweise wird AcceptChanges zu den folgenden Zeitpunkten aufgerufen:

  • Nach dem Laden des Datasets. Wenn Sie ein Dataset laden, indem Sie die Fill-Methode eines TableAdapter aufrufen, führt der Adapter automatisch ein Commit für die Änderungen aus. Wenn ein Dataset jedoch geladen wird, indem Sie ein anderes Dataset mit ihm zusammenführen, müssen Sie den Commit für die Änderungen manuell ausführen.

    Hinweis

    Sie können den Adapter daran hindern, die Änderungen automatisch zu committen. Legen Sie dazu beim Aufruf der Fill-Methode die AcceptChangesDuringFill-Eigenschaft des Adapters auf false fest. Bei einer Festlegung auf false wird der RowState jeder Zeile, die während des Ausfüllens eingefügt wird, auf Added festgelegt.

  • Nachdem Sie Datasetänderungen an einen anderen Prozess gesendet haben, z. B. an einen XML-Webdienst.

    Achtung

    Wenn ein Commit für Änderungen auf diese Weise ausgeführt wird, werden sämtliche Änderungsinformationen gelöscht. Committen Sie Änderungen erst nach dem Abschluss von Vorgängen, bei denen Ihre Anwendung wissen muss, welche Änderungen im Dataset vorgenommen worden sind.

Diese Methode umfasst folgende Schritte:

  • Die Current-Version eines Datensatzes wird in seine Original-Version geschrieben, wobei die ursprüngliche Version überschrieben wird.

  • Entfernt alle Zeilen, deren RowState-Eigenschaft auf Deleted festgelegt ist.

  • Legt die RowState-Eigenschaft eines Datensatzes auf Unchanged fest.

Die AcceptChanges-Methode ist auf drei Ebenen verfügbar. Sie kann für ein DataRow-Objekt aufgerufen werden, um nur Änderungen für diese Zeile zu committen. Sie können sie außerdem für ein DataTable-Objekt aufrufen, um alle Zeilen in einer Tabelle zu committen. Und schließlich können Sie die Methode für das Objekt DataSet aufrufen, um alle ausstehenden Änderungen in sämtlichen Datensätzen aller Tabellen des Datasets zu committen.

In der folgenden Tabelle wird basierend auf dem Objekt, für das die Methode aufgerufen wird, beschrieben, für welche Änderungen ein Commit ausgeführt wird:

Methode Ergebnis
System.Data.DataRow.AcceptChanges Ein Commit wird nur für Änderungen in der spezifischen Zeile ausgeführt.
System.Data.DataTable.AcceptChanges Ein Commit wird für Änderungen in allen Zeilen der spezifischen Tabelle ausgeführt.
System.Data.DataSet.AcceptChanges Ein Commit wird für Änderungen in allen Zeilen der Datasettabellen ausgeführt.

Hinweis

Wenn Sie ein Dataset laden, indem Sie die Fill-Methode eines TableAdapters aufrufen, müssen Sie Änderungen nicht explizit akzeptieren. Standardmäßig ruft die Fill-Methode die AcceptChanges-Methode auf, nachdem sie die Datentabelle aufgefüllt hat.

Eine verwandte Methode (RejectChanges) macht die Auswirkungen von Änderungen rückgängig, indem sie die Original-Version in die Current-Version der Datensätze zurückkopiert. Außerdem wird der RowState jedes Datensatzes wieder auf Unchangedfestgelegt.

Datenüberprüfung

Um sicherzustellen, dass die in der Anwendung enthaltenen Daten die Anforderungen des Prozesses erfüllen, an den sie übergeben werden, sind oftmals Validierungen erforderlich. Dabei wird z. B. überprüft, ob die Benutzereingaben in einem Formular oder die von einer anderen Anwendung an die Anwendung gesendeten Daten korrekt sind. Es kann auch getestet werden, ob die innerhalb der Komponente berechneten Informationen die Einschränkungen der Datenquelle sowie die Anforderungen der Anwendung erfüllen.

Daten können auf verschiedene Weisen überprüft werden:

  • In der Geschäftsschicht, indem der Anwendung Code für Datenüberprüfungen hinzugefügt wird. Dieses Vorgehen ist nur im Dataset möglich. Das Dataset bietet einige Vorteile der Back-End-Validierung, z. B. die Möglichkeit, Änderungen an Spalten- und Zeilenwerten zu überprüfen. Weitere Informationen finden Sie unter Überprüfen von Daten in Datasets.

  • In der Präsentationsschicht, indem Formularen Validierungen hinzugefügt werden. Weitere Informationen finden Sie unter Validierung von Benutzereingaben in Windows Forms.

  • Im Back-End der Datenschicht. Daten werden an die Datenquelle, z. B. die Datenbank, gesendet, und die Datenbank kann diese Daten annehmen oder ablehnen. Bei Verwendung einer Datenbank, die hochentwickelte Datenüberprüfungsmechanismen besitzt und Fehlerinformationen bereitstellt, ist dieser Ansatz durchaus überlegenswert, da Daten unabhängig von ihrer Herkunft überprüft werden können. Möglicherweise werden bei diesem Ansatz jedoch keine anwendungsspezifischen Anforderungen in Bezug auf die Validierung berücksichtigt. Darüber hinaus können aus der Datenvalidierung durch die Datenquelle zahlreiche wiederholte Zugriffe auf die Datenquelle resultieren. Dies hängt davon ab, wie die vom Back-End ausgelösten Validierungsfehler von der Anwendung behandelt werden.

    Wichtig

    Wenn Sie Datenbefehle mit einer CommandType-Eigenschaft mit dem Wert Text verwenden, müssen Sie die von einem Client gesendeten Informationen sorgfältig überprüfen, bevor Sie diese an die Datenbank übergeben. Böswillige Benutzer könnten versuchen, veränderte oder zusätzliche SQL-Anweisungen zu senden (einzufügen), um unautorisierten Zugriff zu erhalten oder die Datenbank zu beschädigen. Bevor Sie Benutzereingaben in eine Datenbank übertragen, vergewissern Sie sich immer, dass die Informationen gültig sind. Nach Möglichkeit sollten Sie immer parametrisierte Abfragen oder gespeicherte Prozeduren verwenden.

Übertragen von Aktualisierungen an die Datenquelle

Nachdem ein Dataset geändert wurde, können Sie die Änderungen an eine Datenquelle übertragen. In den meisten Fällen rufen Sie dazu die Update-Methode eines TableAdapter (oder Datenadapters) auf. Die Methode führt einen Schleifendurchlauf durch jeden Datensatz in einer Datentabelle durch, ermittelt den ggf. erforderlichen Aktualisierungstyp (Aktualisierung, Einfügung oder Löschvorgang) und führt anschließend den geeigneten Befehl aus.

Nehmen wir zur Veranschaulichung des Ablaufs einer Aktualisierung an, dass Ihre Anwendung ein Dataset mit einer einzigen Datentabelle verwendet. Die Anwendung ruft zwei Zeilen aus der Datenbank ab. Nach dem Abruf sieht die Datentabelle im Arbeitsspeicher wie folgt aus:

(RowState)     CustomerID   Name             Status
(Unchanged)    c200         Robert Lyon      Good
(Unchanged)    c400         Nancy Buchanan    Pending

Ihre Anwendung ändert den Status von Nancy Buchanan in „Preferred“. Als Folge dieser Änderung ändert sich der Wert der Eigenschaft RowState für diese Zeile von Unchanged in Modified. Der Wert der RowState-Eigenschaft für die erste Zeile behält den Wert Unchanged bei. Die Datentabelle sieht nun wie folgt aus:

(RowState)     CustomerID   Name             Status
(Unchanged)    c200         Robert Lyon      Good
(Modified)     c400         Nancy Buchanan    Preferred

Anschließend ruft die Anwendung die Update-Methode auf, um das Dataset an die Datenbank zu übertragen. Durch die Methode werden wieder die einzelnen Zeilen untersucht. Für die erste Zeile überträgt die Methode keine SQL-Anweisung an die Datenbank, da diese Zeile seit dem ursprünglichen Abruf aus der Datenbank nicht geändert wurde.

Für die zweite Zeile ruft die Update-Methode jedoch automatisch den geeigneten Datenbefehl auf und überträgt ihn an die Datenbank. Die spezifische Syntax der SQL-Anweisung richtet sich nach der SQL-Sprachvariante, die vom zugrunde liegenden Datenspeicher unterstützt wird. Die folgenden allgemeinen Merkmale der übertragenen SQL-Anweisung sollten jedoch beachtet werden:

  • Die übertragene SQL-Anweisung ist eine UPDATE-Anweisung. Der Adapter nutzt eine UPDATE-Anweisung, da der Wert der Eigenschaft RowStateModified lautet.

  • Die übertragene SQL-Anweisung enthält eine WHERE-Klausel, die als Ziel der UPDATE-Anweisung die Zeile angibt, deren Wert CustomerID = 'c400' lautet. Durch diesen Teil der SELECT-Anweisung wird die Zielzeile von allen anderen Zeilen unterschieden, da die CustomerID der Primärschlüssel der Zieltabelle ist. Falls sich die zur Identifizierung der Zeile benötigten Werte geändert haben, werden die Informationen für die WHERE-Klausel von der ursprünglichen Version des Datensatzes (DataRowVersion.Original) abgeleitet.

  • Die übertragene SQL-Anweisung umfasst die SET-Klausel, mit der der neue Wert geänderter Spalten festgelegt wird.

    Hinweis

    Wenn die UpdateCommand-Eigenschaft des TableAdapter auf den Namen einer gespeicherten Prozedur festgelegt wurde, erstellt der Adapter keine SQL-Anweisung. Stattdessen wird die gespeicherte Prozedur mit den entsprechenden übergebenen Parametern aufgerufen.

Übergeben von Parametern

Normalerweise verwenden Sie Parameter, um die Werte für Datensätze zu übergeben, die in der Datenbank aktualisiert werden. Wenn die Methode Update des TableAdapters eine UPDATE-Anweisung ausführt, müssen die Parameterwerte aufgefüllt werden. Die benötigten Werte werden aus der Parameters-Auflistung des jeweiligen Datenbefehls abgerufen, in diesem Fall ist dies das UpdateCommand-Objekt im TableAdapter.

Wenn der Datenadapter mithilfe der Visual Studio-Tools generiert wurde, enthält das UpdateCommand-Objekt eine Auflistung von Parametern, die dem jeweiligen Parameterplatzhalter in der Anweisung entsprechen.

Die System.Data.SqlClient.SqlParameter.SourceColumn-Eigenschaft der einzelnen Parameter zeigt auf eine Spalte in der Datentabelle. Beispielsweise wird die SourceColumn-Eigenschaft für die Parameter au_id und Original_au_id auf die Spalte in der Datentabelle festgelegt, die die Autoren-ID enthält. Bei Ausführung der Update-Methode des Adapters wird die Spalte mit der Autoren-ID aus dem zu aktualisierenden Datensatz gelesen, und die Werte werden in die Anweisung eingefügt.

In einer UPDATE-Anweisung müssen sowohl die neuen Werte (die in den Datensatz geschrieben werden) als auch die alten Werte angegeben werden (damit der Datensatz in der Datenbank gefunden werden kann). Daher verfügt jeder Wert über zwei Parameter: einen für die SET-Klausel und einen anderen für die WHERE-Klausel. Beide Parameter lesen Daten aus dem zu aktualisierenden Datensatz, aber sie erhalten je nach SourceVersion-Eigenschaft des Parameters unterschiedliche Versionen des Spaltenwerts. Für den Parameter der SET-Klausel wird die aktuelle Version und für den Parameter der WHERE-Klausel die ursprüngliche Version abgerufen.

Hinweis

Sie können auch selbst Werte für die Parameters-Auflistung im Code festlegen. Dies erfolgt in der Regel in einem Ereignishandler für das RowChanging-Ereignis des Datenadapters.