Delen via


Een gelijktijdigheids-uitzondering verwerken in .NET Framework-databasetoepassingen

Opmerking

De DataSet klassen en gerelateerde klassen zijn verouderde .NET Framework-technologieën uit het begin van de jaren 2000 waarmee toepassingen met gegevens in het geheugen kunnen werken terwijl de apps losgekoppeld zijn van de database. De technologieën zijn vooral handig voor apps waarmee gebruikers gegevens kunnen wijzigen en de wijzigingen weer kunnen behouden in de database. Hoewel gegevenssets een bewezen succesvolle technologie zijn, is de aanbevolen aanpak voor nieuwe .NET-toepassingen het gebruik van Entity Framework Core. Entity Framework biedt een natuurlijkere manier om met tabelgegevens te werken als objectmodellen en heeft een eenvoudigere programmeerinterface.

Gelijktijdigheidsonderzondering (System.Data.DBConcurrencyException) wordt gegenereerd wanneer twee gebruikers tegelijkertijd proberen dezelfde gegevens in een database te wijzigen. In deze procedure maakt u een Windows-toepassing die laat zien hoe u een DBConcurrencyException kunt opvangen, de rij kunt vinden die de fout heeft veroorzaakt, en een strategie leert voor het afhandelen ervan.

Bij deze rondleiding doorloopt u het volgende proces:

  1. Maak een nieuw Windows Forms-app (.NET Framework) -project.

  2. Maak een nieuwe gegevensset op basis van de tabel Northwind Customers.

  3. Maak een formulier met een DataGridView om de gegevens weer te geven.

  4. Vul een gegevensset in met gegevens uit de tabel Klanten in de Northwind-database.

  5. Gebruik de functie Tabelgegevens weergeven in Server Explorer om toegang te krijgen tot de gegevens van de tabel Klanten en een record te wijzigen.

  6. Wijzig dezelfde record in een andere waarde, werk de gegevensset bij en probeer de wijzigingen naar de database te schrijven, wat resulteert in een gelijktijdigheidsfout.

  7. Bekijk de fout en geef vervolgens de verschillende versies van de record weer, zodat de gebruiker kan bepalen of de database moet worden voortgezet en bijgewerkt, of de update moet worden geannuleerd.

Vereiste voorwaarden

In dit scenario worden SQL Server Express LocalDB en de Northwind-voorbeelddatabase gebruikt.

  1. Als u geen SQL Server Express LocalDB hebt, installeert u deze via de downloadpagina van SQL Server Express of via het installatieprogramma van Visual Studio. In de Visual Studio Installerkunt u SQL Server Express LocalDB installeren als onderdeel van de Gegevensopslag en -verwerking workload of als een afzonderlijk onderdeel.

  2. Installeer de Northwind-voorbeelddatabase door de volgende stappen uit te voeren:

    1. Open in Visual Studio het venster SQL Server-objectverkenner. (SQL Server Object Explorer wordt geïnstalleerd als onderdeel van de werkbelasting voor gegevensopslag en -verwerking in het Installatieprogramma van Visual Studio.) Vouw het SQL Server-knooppunt uit. Klik met de rechtermuisknop op uw LocalDB-exemplaar en selecteer Nieuwe query.

      Er wordt een venster van de queryeditor geopend.

    2. Kopieer het script Northwind Transact-SQL naar het klembord. Met dit T-SQL-script wordt de volledig nieuwe Northwind-database gemaakt en gevuld met gegevens.

    3. Plak het T-SQL-script in de queryeditor en kies vervolgens de knop uitvoeren.

      Na korte tijd wordt de query uitgevoerd en wordt de Northwind-database gemaakt.

Een nieuw project maken

Begin met het maken van een nieuwe Windows Forms-toepassing:

  1. Selecteer In Visual Studio in het menu Bestand de optie Nieuw>project.

  2. Vouw Visual C# of Visual Basic uit in het linkerdeelvenster en selecteer Vervolgens Windows Desktop.

  3. Selecteer in het middelste deelvenster het projecttype Windows Forms App .

  4. Geef het project de naam ConcurrencyWalkthrough en kies OK.

    Het project ConcurrencyWalkthrough wordt gemaakt en toegevoegd aan Solution Explorer en er wordt een nieuw formulier geopend in de ontwerpfunctie.

De Northwind-gegevensset maken

Maak vervolgens een gegevensset met de naam NorthwindDataSet:

  1. Kies Nieuwe gegevensbron toevoegen in het menu Gegevens.

    De Gegevensbronconfiguratiewizard wordt geopend.

  2. Selecteer Database in het scherm Gegevensbrontype kiezen.

    Gegevensbronconfiguratiewizard in Visual Studio

  3. Selecteer een verbinding met de northwind-voorbeelddatabase in de lijst met beschikbare verbindingen. Als de verbinding niet beschikbaar is in de lijst met verbindingen, selecteert u Nieuwe verbinding.

    Opmerking

    Als u verbinding maakt met een lokaal databasebestand, selecteert u Nee wanneer u wordt gevraagd of u het bestand aan uw project wilt toevoegen.

  4. Selecteer Volgende in het scherm Verbindingsreeks opslaan in het configuratiebestand van de toepassing.

  5. Vouw het knooppunt Tabellen uit en selecteer de tabel Klanten . De standaardnaam voor de gegevensset moet NorthwindDataSet zijn.

  6. Selecteer Voltooien om de gegevensset toe te voegen aan het project.

Een gegevensgebonden DataGridView-besturingselement maken

In deze sectie maakt u een System.Windows.Forms.DataGridView door het item Klanten vanuit het venster Gegevensbronnen naar uw Windows-formulier te slepen.

  1. Als u het venster Gegevensbronnen wilt openen, kiest u in het menu Gegevens de optie Gegevensbronnen weergeven.

  2. Vouw in het venster Gegevensbronnen het knooppunt NorthwindDataSet uit en selecteer vervolgens de tabel Klanten .

  3. Selecteer de pijl-omlaag op het tabelknooppunt en selecteer DataGridView in de vervolgkeuzelijst.

  4. Sleep de tabel naar een leeg gebied van het formulier.

    Een DataGridView besturingselement met de naam CustomersDataGridView en een BindingNavigator met de naam CustomersBindingNavigator worden toegevoegd aan het formulier dat is gebonden aan de BindingSource. Dit is op zijn beurt gebonden aan de tabel Klanten in de NorthwindDataSet.

Het formulier testen

U kunt het formulier nu testen om ervoor te zorgen dat het zich gedraagt zoals verwacht tot dit punt:

  1. Selecteer F5 om de toepassing uit te voeren.

    Het formulier verschijnt met een DataGridView controle die is gevuld met gegevens uit de Klanten-tabel.

  2. Selecteer Foutopsporing stoppen in het menu Foutopsporing.

Gelijktijdigheidsfouten verwerken

Hoe u fouten verwerkt, is afhankelijk van de specifieke bedrijfsregels die van toepassing zijn. Voor deze doorloop gebruiken we de volgende strategie als voorbeeld voor het afhandelen van de concurrentiefout.

De toepassing presenteert de gebruiker met drie versies van de record:

  • De huidige record in de database

  • Het oorspronkelijke bestand dat in de dataset is geladen

  • De voorgestelde wijzigingen in de gegevensset

De gebruiker kan de database vervolgens overschrijven met de voorgestelde versie of de update annuleren en de gegevensset vernieuwen met de nieuwe waarden uit de database.

De verwerking van gelijktijdigheidsfouten inschakelen

  1. Maak een aangepaste fouthandler.

  2. Geef opties weer voor de gebruiker.

  3. Het antwoord van de gebruiker verwerken.

  4. De update opnieuw verzenden of de gegevens in de gegevensset opnieuw instellen.

Code toevoegen om de gelijktijdigheidsondering af te handelen

Wanneer u een update probeert uit te voeren en er een uitzondering wordt gegenereerd, wilt u over het algemeen iets doen met de informatie die wordt verstrekt door de gegenereerde uitzondering. In deze sectie voegt u code toe waarmee de database wordt bijgewerkt. U behandelt ook eventuele DBConcurrencyException-uitzonderingen die kunnen optreden, evenals andere uitzonderingen.

Opmerking

De CreateMessage en ProcessDialogResults methoden worden later in de walkthrough toegevoegd.

  1. Voeg de volgende code toe onder de Form1_Load methode:

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

  1. Vervang de CustomersBindingNavigatorSaveItem_Click methode om de UpdateDatabase methode aan te roepen, zodat deze er als volgt uitziet:

    private void customersBindingNavigatorSaveItem_Click(object sender, EventArgs e)
    {
        UpdateDatabase();
    }
    

Opties weergeven voor de gebruiker

De code die u zojuist hebt geschreven roept de CreateMessage procedure aan om foutinformatie weer te geven aan de gebruiker. Voor deze procedure gebruikt u een berichtvak om de verschillende versies van het record aan de gebruiker te tonen. Hierdoor kan de gebruiker kiezen of de record met de wijzigingen moet worden overschreven of de bewerking moet worden geannuleerd. Zodra de gebruiker een optie selecteert (op een knop klikt) in het berichtvak, wordt het antwoord doorgegeven aan de ProcessDialogResult methode.

Maak het bericht door de volgende code toe te voegen aan de Code-editor. Voer deze code in onder de UpdateDatabase methode:

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[i, RowVersion].ToString() + " ";
    }
    return rowData;
}

Het antwoord van de gebruiker verwerken

U hebt ook code nodig om het antwoord van de gebruiker op het berichtvak te verwerken. De opties zijn het overschrijven van de huidige record in de database met de voorgestelde wijziging, of het afbreken van de lokale wijzigingen en het vernieuwen van de gegevenstabel met de record die zich momenteel in de database bevindt. Als de gebruiker Ja kiest, wordt de Merge methode aangeroepen met het argument preserveChanges ingesteld op true. Dit zorgt ervoor dat de updatepoging is geslaagd, omdat de oorspronkelijke versie van de record nu overeenkomt met de record in de database.

Voeg de volgende code toe onder de code die in de vorige sectie is toegevoegd:

// 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:
            northwindDataSet.Merge(tempCustomersDataTable, true, MissingSchemaAction.Ignore);
            UpdateDatabase();
            break;

        case DialogResult.No:
            northwindDataSet.Merge(tempCustomersDataTable);
            MessageBox.Show("Update cancelled");
            break;
    }
}

Het formuliergedrag testen

U kunt het formulier nu testen om ervoor te zorgen dat het zich gedraagt zoals verwacht. Als u een schending van gelijktijdigheid wilt simuleren, wijzigt u gegevens in de database nadat u northwindDataSet hebt ingevuld.

  1. Selecteer F5 om de toepassing uit te voeren.

  2. Nadat het formulier wordt weergegeven, laat u het actief en schakelt u over naar de Visual Studio IDE.

  3. Kies Server Explorer in het menu Beeld.

  4. Vouw in Server Explorer de verbinding uit die uw toepassing gebruikt en vouw vervolgens het knooppunt Tabellen uit.

  5. Klik met de rechtermuisknop op de tabel Klanten en selecteer Tabelgegevens weergeven.

  6. In de eerste record (ALFKI) wijzigt u ContactName in Maria Anders2.

    Opmerking

    Navigeer naar een andere rij om de wijziging door te voeren.

  7. Schakel over naar het lopende formulier van ConcurrencyWalkthrough.

  8. In de eerste record op het formulier (ALFKI) wijzigt u ContactName in Maria Anders1.

  9. Selecteer de knop Opslaan.

    De gelijktijdigheidsfout wordt gegenereerd en het berichtvak wordt weergegeven.

    Als u Nee selecteert, wordt de update geannuleerd en wordt de gegevensset bijgewerkt met de waarden die zich momenteel in de database bevinden. Als u Ja selecteert, wordt de voorgestelde waarde naar de database geschreven.