Exemplarische Vorgehensweise: Behandeln einer Parallelitätsausnahme

Aktualisiert: November 2007

Parallelitätsausnahmen (DBConcurrencyException) werden ausgelöst, wenn zwei Benutzer gleichzeitig versuchen, dieselben Daten in einer Datenbank zu ändern. In dieser exemplarischen Vorgehensweise erstellen Sie eine Windows-Anwendung zum Abfangen einer DBConcurrencyException, zum Ermitteln der Zeile, die den Fehler ausgelöst hat, und zum Anwenden einer Strategie zur Fehlerbehandlung.

Diese exemplarische Vorgehensweise enthält folgende Vorgänge:

  1. Erstellen eines neuen Projekts vom Typ Windows-Anwendung

  2. Erstellen eines neuen Datasets auf der Grundlage der Tabelle Customers der Datenbank Northwind.

  3. Erstellen eines Formulars mit einer DataGridView für die Anzeige der Daten.

  4. Füllen eines Datasets mit Daten aus der Tabelle Customers in der Datenbank Northwind.

  5. Nach dem Füllen des Datasets verwenden Sie die Visual Database Tools in Visual Studio, um direkt auf die Datentabelle Customers zuzugreifen und einen Datensatz zu ändern.

  6. Ändern Sie im Formular dann einen Wert im gleichen Datensatz, aktualisieren Sie das Dataset und versuchen Sie, die Änderungen in die Datenbank zu schreiben. Dieser Vorgang führt zu einem Parallelitätsfehler.

  7. Fangen Sie den Fehler ab, und zeigen Sie anschließend die verschiedenen Versionen des Datensatzes an, um festzulegen, ob die Aktualisierung der Datenbank fortgesetzt oder abgebrochen werden soll.

Vorbereitungsmaßnahmen

Für die Durchführung dieser exemplarischen Vorgehensweise benötigen Sie Folgendes:

Hinweis:

Je nach den aktiven Einstellungen oder der verwendeten Version können sich die angezeigten Dialogfelder und Menübefehle von den in der Hilfe beschriebenen unterscheiden. Klicken Sie im Menü Extras auf Einstellungen importieren und exportieren, um die Einstellungen zu ändern. Weitere Informationen finden Sie unter Visual Studio-Einstellungen.

Erstellen eines neuen Projekts

Erstellen Sie in dieser exemplarischen Vorgehensweise zunächst eine neue Windows-Anwendung.

So erstellen Sie ein neues Windows-Anwendungsprojekt

  1. Erstellen Sie im Menü Datei ein neues Projekt.

  2. Wählen Sie im Bereich Projekttypen eine Programmiersprache aus.

  3. Wählen Sie Windows-Anwendung im Bereich Vorlagen aus.

  4. Geben Sie dem Projekt den Namen ConcurrencyWalkthrough, und klicken Sie dann auf OK.

    Visual Studio fügt das Projekt dem Projektmappen-Explorer hinzu und zeigt im Designer ein neues Formular an.

Erstellen des Datasets Northwind

In diesem Abschnitt erstellen Sie ein Dataset mit dem Namen NorthwindDataSet.

So erstellen Sie das NorthwindDataset

  1. Wählen Sie im Menü Daten die Option Neue Datenquelle hinzufügen aus.

    Der Assistent zum Konfigurieren von Datenquellen wird geöffnet.

  2. Wählen Sie auf der Seite Datenquellentyp auswählen die Option Datenbank aus.

  3. Wählen Sie in der Liste der verfügbaren Verbindungen eine Verbindung zur Beispieldatenbank Northwind aus, oder klicken Sie auf Neue Verbindung, falls die Verbindung nicht in der Liste verfügbar ist.

    Hinweis:

    Beim Herstellen einer Verbindung zu einer lokalen Datenbankdatei wählen Sie Nein, wenn Sie gefragt werden, ob die Datei Ihrem Projekt hinzugefügt werden soll.

  4. Klicken Sie auf der Seite Verbindungszeichenfolge in der Programmkonfigurationsdatei speichern auf Weiter.

  5. Erweitern Sie den Knoten Tabellen, und wählen Sie die Tabelle Customers aus. Der Standardname für das Dataset sollte NorthwindDataSet sein.

  6. Klicken Sie auf Fertig stellen, um dem Projekt das Dataset hinzuzufügen.

Erstellen eines datengebundenen DataGridView-Steuerelements

In diesem Abschnitt erstellen Sie ein DataGridView, indem Sie das Customers-Objekt aus dem Datenquellenfenster auf das Windows Form ziehen.

So erstellen Sie ein DataGridView-Steuerelement, das an die Tabelle Customers gebunden ist

  1. Wählen Sie im Menü Daten den Befehl Datenquellen anzeigen aus, um das Datenquellenfenster zu öffnen.

  2. Im Datenquellenfenster erweitern Sie den Knoten NorthwindDataSet und wählen Sie die Tabelle Customers aus.

  3. Klicken Sie auf den nach unten zeigenden Pfeil des Tabellenknotens, und wählen Sie DataGridView in der Dropdownliste aus.

  4. Ziehen Sie die Tabelle auf einen leeren Bereich des Formulars.

    Dem Formular werden das DataGridView-Steuerelement CustomersDataGridView und das BindingNavigatorCustomersBindingNavigator hinzugefügt, die an die BindingSource gebunden werden, die wiederum an die Tabelle Customers im NorthwindDataSet gebunden ist.

Checkpoint

Sie können das Formular jetzt testen, um sicherzustellen, dass das Verhalten bisher wie erwartet ausfällt.

So testen Sie das Formular

  1. Drücken Sie F5, um die Anwendung auszuführen.

    Das Formular wird mit einem DataGridView-Steuerelement angezeigt, das mit Daten aus der Tabelle Customers gefüllt ist.

  2. Wählen Sie im Menü Debuggen die Option Debuggen beenden.

Behandeln von Parallelitätsfehlern

Wie Sie Fehler behandeln, hängt von den jeweiligen Geschäftsregeln ab, nach denen die Anwendung abläuft. In dieser exemplarischen Vorgehensweise wird zu Demonstrationszwecken nach dem Auslösen einer Parallelitätsverletzung die folgende Strategie zum Behandeln des Parallelitätsfehlers verwendet:

Die Anwendung bietet dem Benutzer drei Versionen des Datensatzes zur Auswahl:

  • Den aktuellen Datensatz in der Datenbank

  • Den ursprünglich in das Dataset geladenen Datensatz

  • Die vorgeschlagenen Änderungen im Dataset

Der Benutzer kann dann die Datenbank mit der vorgeschlagenen Version überschreiben oder aber die Aktualisierung abbrechen und das Dataset mit den neuen Werten aus der Datenbank aktualisieren.

So aktivieren Sie die Behandlung von Parallelitätsfehlern

  1. Erstellen Sie einen benutzerdefinierten Fehlerhandler.

  2. Zeigen Sie die Auswahloptionen für den Benutzer an.

  3. Verarbeiten Sie die Eingabe des Benutzers.

  4. Senden Sie die Aktualisierung erneut, oder setzen Sie die Daten im Dataset zurück.

Hinzufügen von Code zum Behandeln von Parallelitätsausnahmen

Wenn bei einem Aktualisierungsversuch eine Ausnahme ausgelöst wird, sind die Informationen, die zusammen mit der ausgelösten Ausnahme angezeigt werden, in der Regel sehr hilfreich.

In diesem Abschnitt fügen Sie Code hinzu, der versucht, die Datenbank zu aktualisieren, und behandeln jede ausgelöste DBConcurrencyException sowie alle anderen Ausnahmen.

Hinweis:

Die CreateMessage-Methode und die ProcessDialogResults-Methode werden zu einem späteren Zeitpunkt in dieser exemplarischen Vorgehensweise hinzugefügt.

So fügen Sie Fehlerbehandlungscode für den Parallelitätsfehler hinzu

  1. Fügen Sie unter der Form1_Load-Methode folgenden Code hinzu:

    Private Sub UpdateDatabase()
    
        Try
            Me.CustomersTableAdapter.Update(Me.NorthwindDataSet.Customers)
            MsgBox("Update successful")
    
        Catch dbcx As Data.DBConcurrencyException
            Dim response As Windows.Forms.DialogResult
    
            response = MessageBox.Show(CreateMessage(CType(dbcx.Row, NorthwindDataSet.CustomersRow)), _
                "Concurrency Exception", MessageBoxButtons.YesNo)
    
            ProcessDialogResult(response)
    
        Catch ex As Exception
            MsgBox("An error was thrown while attempting to update the database.")
        End Try
    End Sub
    
    private void UpdateDatabase()
    {
        try
        {
            this.customersTableAdapter.Update(this.northwindDataSet.Customers);
            MessageBox.Show("Update successful");
        }
        catch (DBConcurrencyException dbcx)
        {
            DialogResult response = MessageBox.Show(CreateMessage((NorthwindDataSet.CustomersRow)
                (dbcx.Row)), "Concurrency Exception", MessageBoxButtons.YesNo);
    
            ProcessDialogResult(response);
        }
        catch (Exception ex)
        {
            MessageBox.Show("An error was thrown while attempting to update the database.");
        }
    }
    
  2. Ersetzen Sie die CustomersBindingNavigatorSaveItem_Click-Methode, um die UpdateDatabase-Methode aufzurufen, sodass sich Folgendes ergibt:

    Private Sub CustomersBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CustomersBindingNavigatorSaveItem.Click
        UpdateDatabase()
    End Sub
    
    private void customersBindingNavigatorSaveItem_Click(object sender, EventArgs e)
    {
        UpdateDatabase();
    }
    

Anzeigen der Auswahloptionen für den Benutzer

Durch den soeben geschriebenen Code wird die CreateMessage-Prozedur aufgerufen, um Fehlerinformationen für den Benutzer anzuzeigen. In dieser exemplarischen Vorgehensweise wird ein Meldungsfeld verwendet, um dem Benutzer die verschiedenen Versionen des Datensatzes anzuzeigen. Er kann daraufhin auswählen, ob er den Datensatz mit den Änderungen überschreibt oder die Bearbeitung abbricht. Wenn der Benutzer durch Klicken auf eine Schaltfläche eine Option im Meldungsfeld ausgewählt hat, wird die Antwort an die ProcessDialogResult-Methode übergeben.

So erstellen Sie die Meldung, die dem Benutzer angezeigt wird

  • Erstellen Sie die Meldung, indem Sie dem Code-Editor folgenden Code hinzufügen. Geben Sie diesen Code unter der UpdateDatabase-Methode ein.

    Private Function CreateMessage(ByVal cr As NorthwindDataSet.CustomersRow) As String
        Return _
            "Database: " & GetRowData(GetCurrentRowInDB(cr), Data.DataRowVersion.Default) & vbCrLf & _
            "Original: " & GetRowData(cr, Data.DataRowVersion.Original) & vbCrLf & _
            "Proposed: " & GetRowData(cr, Data.DataRowVersion.Current) & vbCrLf & _
            "Do you still want to update the database with the proposed value?"
    End Function
    
    
    '--------------------------------------------------------------------------
    ' This method loads a temporary table with current records from the database
    ' and returns the current values from the row that caused the exception.
    '--------------------------------------------------------------------------
    Private TempCustomersDataTable As New NorthwindDataSet.CustomersDataTable
    
    Private Function GetCurrentRowInDB(ByVal RowWithError As NorthwindDataSet.CustomersRow) _
        As NorthwindDataSet.CustomersRow
    
        Me.CustomersTableAdapter.Fill(TempCustomersDataTable)
    
        Dim currentRowInDb As NorthwindDataSet.CustomersRow = _
            TempCustomersDataTable.FindByCustomerID(RowWithError.CustomerID)
    
        Return currentRowInDb
    End Function
    
    
    '--------------------------------------------------------------------------
    ' This method takes a CustomersRow and RowVersion 
    ' and returns a string of column values to display to the user.
    '--------------------------------------------------------------------------
    Private Function GetRowData(ByVal custRow As NorthwindDataSet.CustomersRow, _
        ByVal RowVersion As Data.DataRowVersion) As String
    
        Dim rowData As String = ""
    
        For i As Integer = 0 To custRow.ItemArray.Length - 1
            rowData += custRow.Item(i, RowVersion).ToString() & " "
        Next
    
        Return rowData
    End Function
    
    private string CreateMessage(NorthwindDataSet.CustomersRow cr)
    {
        return
            "Database: " + GetRowData(GetCurrentRowInDB(cr), DataRowVersion.Default) + "\n" +
            "Original: " + GetRowData(cr, DataRowVersion.Original) + "\n" +
            "Proposed: " + GetRowData(cr, DataRowVersion.Current) + "\n" +
            "Do you still want to update the database with the proposed value?";
    }
    
    
    //--------------------------------------------------------------------------
    // This method loads a temporary table with current records from the database
    // and returns the current values from the row that caused the exception.
    //--------------------------------------------------------------------------
    private NorthwindDataSet.CustomersDataTable tempCustomersDataTable = 
        new NorthwindDataSet.CustomersDataTable();
    
    private NorthwindDataSet.CustomersRow GetCurrentRowInDB(NorthwindDataSet.CustomersRow RowWithError)
    {
        this.customersTableAdapter.Fill(tempCustomersDataTable);
    
        NorthwindDataSet.CustomersRow currentRowInDb = 
            tempCustomersDataTable.FindByCustomerID(RowWithError.CustomerID);
    
        return currentRowInDb;
    }
    
    
    //--------------------------------------------------------------------------
    // This method takes a CustomersRow and RowVersion 
    // and returns a string of column values to display to the user.
    //--------------------------------------------------------------------------
    private string GetRowData(NorthwindDataSet.CustomersRow custRow, DataRowVersion RowVersion)
    {
        string rowData = "";
    
        for (int i = 0; i < custRow.ItemArray.Length ; i++ )
        {
            rowData = rowData + custRow.Item(i, RowVersion).ToString() + " ";
        }
        return rowData;
    }
    

Verarbeiten der Eingabe des Benutzers

Sie benötigen außerdem Code, um die Reaktion des Benutzers auf das Meldungsfeld zu verarbeiten. Der Benutzer kann entweder den aktuellen Datensatz in der Datenbank mit der vorgeschlagenen Änderung überschreiben oder die lokalen Änderungen verwerfen und die Datentabelle mit dem aktuell in der Datenbank vorhandenen Datensatz aktualisieren. Wenn der Benutzer Ja wählt, wird die Merge-Methode mit dem preserveChanges-Argument mit der Einstellung true aufgerufen. Der Aktualisierungsversuch verläuft somit erfolgreich, da die ursprüngliche Version des Datensatzes nun mit dem Datensatz in der Datenbank übereinstimmt.

So verarbeiten Sie die Benutzereingabe aus dem Meldungsfeld

  • Fügen Sie den folgenden Code unter dem im vorherigen Abschnitt hinzugefügten Code hinzu.

    ' This method takes the DialogResult selected by the user and updates the database 
    ' with the new values or cancels the update and resets the Customers table 
    ' (in the dataset) with the values currently in the database.
    
    Private Sub ProcessDialogResult(ByVal response As Windows.Forms.DialogResult)
    
        Select Case response
    
            Case Windows.Forms.DialogResult.Yes
                NorthwindDataSet.Customers.Merge(TempCustomersDataTable, True)
                UpdateDatabase()
    
            Case Windows.Forms.DialogResult.No
                NorthwindDataSet.Customers.Merge(TempCustomersDataTable)
                MsgBox("Update cancelled")
        End Select
    End Sub
    
    // This method takes the DialogResult selected by the user and updates the database 
    // with the new values or cancels the update and resets the Customers table 
    // (in the dataset) with the values currently in the database.
    
    private void ProcessDialogResult(DialogResult response)
    {
        switch (response)
        {
            case DialogResult.Yes:
                UpdateDatabase();
                break;
    
            case DialogResult.No:
                northwindDataSet.Merge(tempCustomersDataTable);
                MessageBox.Show("Update cancelled");
                break;
        }
    }
    

Testen

Sie können das Formular jetzt testen, um sicherzustellen, dass das Verhalten wie erwartet ausfällt. Um eine Parallelitätsverletzung zu simulieren, müssen Sie Daten in der Datenbank ändern, nachdem Sie das NorthwindDataSet gefüllt haben.

So testen Sie das Formular

  1. Drucken Sie F5, um die Anwendung auszuführen.

  2. Wenn das Formular angezeigt wird, führen Sie es weiterhin, und wechseln Sie zur Visual Studio-IDE.

  3. Klicken Sie im Menü Ansicht auf Server-Explorer.

  4. Erweitern Sie im Server-Explorer die Verbindung, die von der Anwendung verwendet wird, und erweitern Sie den Knoten Tabellen.

  5. Klicken Sie mit der rechten Maustaste auf die Tabelle Customers, und wählen Sie Tabellendaten anzeigen aus.

  6. Ändern Sie im ersten Datensatz (ALFKI) den ContactName in Maria Anders2.

    Hinweis:

    Navigieren Sie zu einer anderen Zeile, um einen Commit für die Änderung auszuführen.

  7. Wechseln Sie zum Formular ConcurrencyWalkthrough, das immer noch ausgeführt wird.

  8. Ändern Sie im ersten Datensatz des Formulars (ALFKI) den ContactName in Maria Anders1.

  9. Klicken Sie auf die Schaltfläche Speichern.

    Der Parallelitätsfehler wird ausgelöst, und das Meldungsfeld wird angezeigt.

  10. Wenn Sie auf Nein klicken, wird die Aktualisierung abgebrochen und das Dataset mit den aktuellen Werten in der Datenbank aktualisiert. Wenn Sie hingegen auf Ja klicken, wird der vorgeschlagene Wert in die Datenbank geschrieben.

Siehe auch

Konzepte

Neue Datenfeatures

Übersicht über das Anzeigen von Daten

Weitere Ressourcen

Exemplarische Vorgehensweisen zur Arbeit mit Daten

Herstellen von Datenverbindungen in Visual Studio

Vorbereiten der Anwendung auf den Empfang von Daten

Abrufen von Daten für die Anwendung

Anzeigen von Daten in Formularen in Windows-Anwendungen

Bearbeiten von Daten in der Anwendung

Überprüfen von Daten

Speichern von Daten