Freigeben über


Hierarchisches Update in .NET Framework-Entwicklung

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.

Hierarchische Updates meinen das Zurückspeichern aktualisierter Daten (aus einem Dataset mit zwei oder mehr verknüpften Tabellen) in eine Datenbank unter Einhaltung von Regeln zur referenziellen Integrität. Die referenzielle Integrität bezieht sich auf die Konsistenzregeln, die von den Beschränkungen in einer Datenbank bereitgestellt werden, die das Verhalten beim Einfügen, Aktualisieren und Löschen von verknüpften Datensätzen steuern. Beispielsweise ist es referenzielle Integrität, die die Erstellung eines Kundendatensatzes erzwingt, bevor Bestellungen für diesen Kunden erstellt werden können. Weitere Informationen zu Beziehungen in Datasets finden Sie unter Erstellen von Beziehungen zwischen Datasets.

Das hierarchische Updatefeature verwendet einen TableAdapterManager zum Verwalten der TableAdapter in einem typisierten Dataset. Die TableAdapterManager-Komponente ist eine von Visual Studio generierte Klasse, nicht ein .NET-Typ. Wenn Sie eine Tabelle aus dem Fenster Datenquellen auf eine Windows Form- oder WPF-Seite ziehen, fügt Visual Studio dem Formular oder der Seite eine Variable vom Typ „TableAdapterManager“ hinzu, und sie wird im Designer auf der Komponentenleiste angezeigt. Ausführliche Informationen zur TableAdapterManager-Klasse finden Sie im Referenzabschnitt zu TableAdapterManager von TableAdapters.

Standardmäßig werden verknüpfte Tabellen in einem Dataset „nur als Beziehungen“ behandelt, was bedeutet, dass keine Fremdschlüsseleinschränkungen erzwungen werden. Sie können diese Einstellung zur Entwurfszeit ändern, indem Sie den DataSet-Designer verwenden. Wählen Sie die Beziehungslinie zwischen zwei Tabellen aus, um das Dialogfeld Beziehung anzuzeigen. Die hier vorgenommenen Änderungen bestimmen, wie sich TableAdapterManager verhält, wenn er die Änderungen in den verknüpften Tabellen an die Datenbank zurücksendet.

Aktivieren der hierarchischen Updates in einem Dataset

Standardmäßig wird die hierarchische Aktualisierung für alle neuen DataSets aktiviert, die in einem Projekt hinzugefügt oder erstellt werden. Aktivieren oder deaktivieren Sie hierarchische Updates, indem Sie die Eigenschaft Hierarchisches Update eines typisierten Datasets im Dataset auf True oder False festlegen:

Einstellungen der hierarchischen Updates

Erstellen einer neuen Beziehung zwischen Tabellen

Um eine neue Beziehung zwischen zwei Tabellen zu erstellen, wählen Sie im DataSet-Designer die Titelleiste jeder Tabelle aus, klicken Sie dann mit der rechten Maustaste, und wählen Sie Beziehung hinzufügen aus.

Das Menü zum Hinzufügen einer Beziehung für hierarchische Updates

Grundlegendes zu Fremdschlüsseleinschränkungen, Updateweitergaben und Löschungen

Es ist wichtig, dass Sie nachvollziehen können, wie die Fremdschlüsseleinschränkungen und das Weitergabeverhalten in der Datenbank im generierten DataSet-Code erstellt werden.

Standardmäßig werden die Datentabellen in einem DataSet mit Beziehungen (DataRelation) generiert, die den Beziehungen in der Datenbank entsprechen. Jedoch wird die Beziehung im DataSet nicht als Fremdschlüsseleinschränkung generiert. Die DataRelation wird als Nur Beziehung konfiguriert, ohne dass UpdateRule oder DeleteRule wirksam sind.

Standardmäßig sind Aktualisierungs- und Löschweitergaben deaktiviert, auch wenn Aktualisierungs- oder Löschweitergaben für die Datenbankbeziehung aktiviert sind. Beispielsweise kann das Erstellen eines neuen Kunden und einer neuen Bestellung sowie das anschließende Speichern der Daten einen Konflikt mit den in der Datenbank definierten Fremdschlüsseleinschränkungen verursachen. Weitere Informationen finden Sie unter Deaktivieren von Einschränkungen beim Auffüllen von Datasets.

Festlegen der Reihenfolge zum Ausführen von Updates

Durch das Festlegen der Reihenfolge, in der Updates durchgeführt werden, wird die Reihenfolge der einzelnen Einfüge-, Update- und Löschvorgänge festgelegt, die erforderlich sind, um die gesamten geänderten Daten in allen Tabellen eines Datasets zu speichern. Wenn das hierarchische Update aktiviert ist, werden zuerst die Einfüge-, dann die Update- und anschließend die Löschvorgänge durchgeführt. Der TableAdapterManager stellt die UpdateOrder-Eigenschaft bereit, die Sie setzen können, um zuerst die Updates und dann die Einfüge- und Löschvorgänge durchzuführen.

Hinweis

Beachten Sie unbedingt, dass die Updatereihenfolge für alle Vorgänge gilt. Dies bedeutet, dass bei der Durchführung von Updates für alle Tabellen im Dataset Einfüge-, dann Update- und dann Löschvorgänge ausgeführt werden.

Wenn Sie die UpdateOrder-Eigenschaft festlegen möchten, wählen Sie nach dem Ziehen von Elementen aus dem Fenster Datenquellen auf ein Formular den TableAdapterManager auf der Komponentenleiste aus, und legen Sie dann die UpdateOrder-Eigenschaft im Fenster Eigenschaften fest.

Erstellen einer Sicherungskopie eines Datasets vor dem Ausführen eines hierarchischen Updates

Beim Speichern von Daten (durch Aufrufen der TableAdapterManager.UpdateAll()-Methode) aktualisiert der TableAdapterManager die Daten für jede Tabelle in einer einzelnen Transaktion. Wenn ein Teil der Aktualisierung für eine Tabelle fehlschlägt, wird für die gesamte Transaktion ein Rollback ausgeführt. In den meisten Fällen wird die Anwendung durch ein Rollback in ihren ursprünglichen Zustand zurückgesetzt.

Manchmal möchten Sie das DataSet jedoch möglicherweise aus der Sicherungskopie wiederherstellen, Ein Beispiel hierfür ist die Verwendung von automatisch inkrementierenden Werten. Wenn beispielsweise ein Speichervorgang nicht erfolgreich ist, werden die automatisch inkrementierenden Werte im Dataset nicht zurückgesetzt, und das Dataset erstellt weiterhin automatisch inkrementierende Werte. Dadurch entsteht eine Lücke in der Nummerierung, die in Ihrer Anwendung möglicherweise nicht zulässig ist. Für Fälle, in denen dies zu einem Problem führt, stellt der TableAdapterManager die BackupDataSetBeforeUpdate-Eigenschaft bereit, durch die das vorhandene DataSet beim Fehlschlagen der Transaktion durch eine Sicherungskopie ersetzt wird.

Hinweis

Die Sicherungskopie befindet sich nur im Arbeitsspeicher, während die TableAdapterManager.UpdateAll-Methode ausgeführt wird. Deshalb können Sie auf dieses gesicherte Dataset nicht programmgesteuert zugreifen, da es das ursprüngliche Dataset ersetzt oder ungültig wird, sobald die Ausführung der TableAdapterManager.UpdateAll-Methode beendet ist.

Ändern des generierten Speichercodes zum Ausführen des hierarchischen Updates

Speichern Sie die Änderungen der verknüpften Tabellen im Dataset in der Datenbank, indem Sie die Methode TableAdapterManager.UpdateAll aufrufen und den Namen des Datasets übergeben, der die verknüpften Tabellen enthält. Führen Sie zum Beispiel die Methode TableAdapterManager.UpdateAll(NorthwindDataset) aus, um Aktualisierungen von allen Tabellen im NorthwindDataset zur Back-End-Datenbank zu senden.

Nachdem Sie die Elemente aus dem Fenster Datenquellen abgelegt haben, wird der Code automatisch dem Form_Load-Ereignis für das Füllen jeder Tabelle hinzugefügt (den TableAdapter.Fill-Methoden). Es wird auch Code zum Click-Ereignis der Schaltfläche Speichern des BindingNavigator hinzugefügt, sodass die Daten des Datasets wieder in der Datenbank gespeichert werden (der TableAdapterManager.UpdateAll-Methode).

Der generierte Speichern-Code enthält eine Codezeile, die die Methode CustomersBindingSource.EndEdit aufruft. Genauer gesagt ruft er die EndEdit-Methode der ersten BindingSource auf, die dem Formular hinzugefügt wurde. Anders ausgedrückt: Dieser Code wird nur für die erste Tabelle erzeugt, die vom Fenster Datenquellen auf das Formular gezogen wird. Der Aufruf EndEdit führt ein Commit aller Änderungen durch, die in irgendeinem datengebundenen Steuerelement ablaufen, das derzeit bearbeitet wird. Wenn also ein datengebundenes Steuerelement den Fokus noch besitzt und Sie auf Speichern klicken, werden alle ausstehenden Bearbeitungen in diesem Steuerelement committet, bevor der eigentliche Speichervorgang durchgeführt wird (die TableAdapterManager.UpdateAll-Methode).

Hinweis

Der DataSet-Designer fügt nur den BindingSource.EndEdit-Code für die erste Tabelle hinzu, die auf dem Formular abgelegt wird. Sie müssen deshalb eine Codezeile zum Aufruf der BindingSource.EndEdit-Methode für jede verknüpfte Tabelle auf dem Formular hinzufügen. Für diese exemplarische Vorgehensweise heißt das, dass Sie einen Aufruf zur OrdersBindingSource.EndEdit-Methode hinzufügen müssen.

  1. Doppelklicken Sie auf BindingNavigator auf Speichern, um Form1 im Code-Editor zu öffnen.

  2. Fügen Sie eine Codezeile ein, um die OrdersBindingSource.EndEdit-Methode nach der Zeile aufzurufen, die die CustomersBindingSource.EndEdit-Methode aufruft. Der Code im Click-Ereignis Speichern sollte etwa wie folgt aussehen:

    this.Validate();
    this.customersBindingSource.EndEdit();
    this.ordersBindingSource.EndEdit();
    this.tableAdapterManager.UpdateAll(this.northwindDataSet);
    

Neben dem Commit für Änderungen an einer verknüpften untergeordneten Tabelle vor dem Speichern in einer Datenbank müssen Sie vielleicht einen einen Commit der neue erstellten übergeordneten Datensätze durchführen, ehe Sie neue untergeordnete Datensätze dem Dataset hinzufügen. Anders ausgedrückt: Sie müssen möglicherweise den neuen übergeordneten Datensatz (Customer) dem Dataset hinzufügen, bevor es die Fremdschlüsseleinschränkungen ermöglichen, dass dem Dataset neue untergeordnete Datensätze (Orders) hinzugefügt werden können. Das erreichen Sie, indem Sie das untergeordnete BindingSource.AddingNew-Ereignis verwenden.

Hinweis

Ob Sie neue übergeordnete Datensätze übernehmen müssen, hängt vom Typ des Steuerelements ab, das zum Binden an Ihre Datenquelle verwendet wird. In dieser exemplarischen Vorgehensweise verwenden Sie einzelne Steuerelemente für das Binden an die übergeordnete Tabelle. Dazu ist ein zusätzlicher Code erforderlich, um den neuen übergeordneten Datensatz zu committen. Wenn die übergeordneten Datensätze stattdessen in einem komplexen Bindungssteuerelement wie der DataGridView angezeigt werden, wäre dieser zusätzliche EndEdit-Aufruf für den übergeordneten Datensatz nicht nötig. Das liegt daran, dass die zugrunde liegende Datenbindungsfunktion des Steuerelements den Commit neuer Datensätze übernimmt.

So fügen Sie Code für den Commit übergeordneter Datensätze hinzu, ehe untergeordnete Datensätze hinzufügt werden

  1. Erstellen Sie einen Ereignishandler für das OrdersBindingSource.AddingNew-Ereignis.

    • Öffnen Sie Form1 in der Entwurfsansicht, wählen Sie OrdersBindingSource auf der Komponentenleiste aus, wählen Sie Ereignisse im Fenster Eigenschaften aus, und klicken Sie dann doppelt auf das Ereignis AddingNew.
  2. Fügen Sie dem Ereignishandler eine Codezeile hinzu, die die CustomersBindingSource.EndEdit-Methode aufruft. Der Code im Ereignis OrdersBindingSource_AddingNew sollte etwa folgendermaßen aussehen:

    this.customersBindingSource.EndEdit();
    

TableAdapterManager-Referenz

Standardmäßig wird eine TableAdapterManager-Klasse generiert, wenn Sie ein Dataset erstellen, das verknüpfte Tabellen enthält. Um zu verhindern, dass die Klasse generiert wird, ändern Sie den Wert der Hierarchical Update-Eigenschaft des Datasets in „False“. Wenn Sie eine Tabelle mit einer Beziehung auf die Entwurfsoberfläche einer Windows Form- oder WPF-Seite ziehen, deklariert Visual Studio eine Membervariable der Klasse. Wenn Sie keine Datenbindung verwenden, müssen Sie die Variable manuell deklarieren.

Die TableAdapterManager-Klasse ist kein .NET-Typ. Daher finden Sie darüber keine Informationen in der Dokumentation. Sie wird zur Entwurfszeit im Rahmen des Dataseterstellungsprozesses erstellt.

Im Folgenden werden die häufig verwendeten Methoden und Eigenschaften der TableAdapterManager-Klasse aufgeführt:

Member BESCHREIBUNG
UpdateAll-Methode Speichert alle Daten aus allen Datentabellen.
BackUpDataSetBeforeUpdate-Eigenschaft Boolescher Wert, der angibt, ob vor dem Ausführen der TableAdapterManager.UpdateAll-Methode eine Sicherungskopie des Datasets erstellt werden soll.
Eigenschaft tableName TableAdapter Stellt einen TableAdapter dar. Der generierte TableAdapterManager enthält eine Eigenschaft für jeden verwalteten TableAdapter. So wird beispielsweise ein Datensatz mit einer Tabelle „Customers“ und „Orders“ mit einem TableAdapterManager erzeugt, der die Eigenschaften CustomersTableAdapter und OrdersTableAdapter enthält.
UpdateOrder-Eigenschaft Steuert die Reihenfolge der einzelnen Einfüge-, Aktualisierungs- und Löschbefehle. Legen Sie dies als einen der Werte in der TableAdapterManager.UpdateOrderOption-Enumeration fest.

Standardmäßig ist UpdateOrder auf InsertUpdateDelete festgelegt. Dies bedeutet, dass für alle Tabellen im Dataset Einfüge-, dann Update- und dann Löschvorgänge ausgeführt werden.