Partager via


Gérer une exception d’accès concurrentiel dans les applications de base de données .NET Framework

Remarque

La DataSet classe et les classes associées sont des technologies .NET Framework héritées du début des années 2000 qui permettent aux applications d’utiliser des données en mémoire pendant que les applications sont déconnectées de la base de données. Les technologies sont particulièrement utiles pour les applications qui permettent aux utilisateurs de modifier les données et de conserver les modifications apportées à la base de données. Bien que les jeux de données soient une technologie éprouvée, l’approche recommandée pour les nouvelles applications .NET consiste à utiliser Entity Framework Core. Entity Framework offre un moyen plus naturel d’utiliser des données tabulaires en tant que modèles objet et dispose d’une interface de programmation plus simple.

Les exceptions de concurrence (System.Data.DBConcurrencyException) sont déclenchées lorsque deux utilisateurs tentent de modifier les mêmes données dans une base de données en même temps. Dans cette procédure pas à pas, vous créez une application Windows qui montre comment intercepter un DBConcurrencyException, localiser la ligne qui a provoqué l’erreur et apprendre une stratégie pour la gérer.

Cette procédure pas à pas vous guide tout au long du processus suivant :

  1. Créez un projet d’application Windows Forms (.NET Framework).

  2. Créez un jeu de données basé sur la table "Northwind Customers".

  3. Créez un formulaire avec un DataGridView pour afficher les données.

  4. Remplissez un jeu de données avec des données de la table Customers dans la base de données Northwind.

  5. Utilisez la fonctionnalité Afficher les données de table dans l’Explorateur de serveurs pour accéder aux données de la table Customers et modifier un enregistrement.

  6. Modifiez le même enregistrement à une valeur différente, mettez à jour l'ensemble de données et tentez d'écrire les modifications dans la base de données, ce qui provoque une erreur de concurrence.

  7. Interceptez l’erreur, puis affichez les différentes versions de l’enregistrement, ce qui permet à l’utilisateur de déterminer s’il faut continuer et mettre à jour la base de données ou annuler la mise à jour.

Conditions préalables

Cette procédure pas à pas utilise SQL Server Express LocalDB et l’exemple de base de données Northwind.

  1. Si sql Server Express LocalDB n’est pas installé, installez-le à partir de la page de téléchargement SQL Server Express ou via Visual Studio Installer. Dans Visual Studio Installer, vous pouvez installer SQL Server Express LocalDB dans le cadre du stockage et du traitement des données charge de travail, ou en tant que composant individuel.

  2. Installez l’exemple de base de données Northwind en procédant comme suit :

    1. Dans Visual Studio, ouvrez la fenêtre de l’Explorateur d’objets SQL Server. (L’Explorateur d’objets SQL Server est installé dans le cadre de la charge de travail de stockage et de traitement des données dans Visual Studio Installer.) Développez le nœud SQL Server . Cliquez avec le bouton droit sur votre instance LocalDB, puis sélectionnez nouvelle requête.

      Une fenêtre de l’éditeur de requête s’ouvre.

    2. Copiez le script Northwind Transact-SQL dans votre presse-papiers. Ce script T-SQL crée la base de données Northwind à partir de zéro et la remplit avec des données.

    3. Collez le script T-SQL dans l’éditeur de requête, puis choisissez le bouton Exécuter.

      Après un court laps de temps, la requête se termine et la base de données Northwind est créée.

Créer un projet

Commencez par créer une application Windows Forms :

  1. Dans Visual Studio, dans le menu Fichier, sélectionnez Nouveau>Projet.

  2. Développez Visual C# ou Visual Basic dans le volet gauche, puis sélectionnez Bureau Windows.

  3. Dans le volet central, sélectionnez le type de projet d’application Windows Forms .

  4. Nommez le projet ConcurrencyWalkthrough, puis choisissez OK.

    Le projet ConcurrencyWalkthrough est créé et ajouté à l’Explorateur de solutions, et un nouveau formulaire s’ouvre dans le concepteur.

Créer le jeu de données Northwind

Ensuite, créez un jeu de données nommé NorthwindDataSet :

  1. Dans le menu Données , choisissez Ajouter une nouvelle source de données.

    L’Assistant Configuration de source de données s’ouvre.

  2. Dans l’écran Choisir un type de source de données , sélectionnez Base de données.

    Assistant de configuration des sources de données dans Visual Studio

  3. Sélectionnez une connexion à l’échantillon de base de données Northwind dans la liste des connexions disponibles. Si la connexion n’est pas disponible dans la liste des connexions, sélectionnez Nouvelle connexion.

    Remarque

    Si vous vous connectez à un fichier de base de données local, sélectionnez Non quand vous souhaitez ajouter le fichier à votre projet.

  4. Dans l’écran Enregistrer la chaîne de connexion dans l’écran du fichier de configuration de l’application , sélectionnez Suivant.

  5. Développez le nœud Tables et sélectionnez la table Customers . Le nom par défaut du jeu de données doit être NorthwindDataSet.

  6. Sélectionnez Terminer pour ajouter le jeu de données au projet.

Créer un contrôle DataGridView lié aux données

Dans cette section, vous créez un System.Windows.Forms.DataGridView en faisant glisser l’élément Customers de la fenêtre Sources de données vers votre Windows Form.

  1. Pour ouvrir la fenêtre Sources de données , dans le menu Données , choisissez Afficher les sources de données.

  2. Dans la fenêtre Sources de données , développez le nœud NorthwindDataSet , puis sélectionnez la table Customers .

  3. Sélectionnez la flèche vers le bas sur le nœud du tableau, puis sélectionnez DataGridView dans la liste déroulante.

  4. Faites glisser la table sur une zone vide de votre formulaire.

    Un DataGridView contrôle nommé CustomersDataGridView, et un BindingNavigator contrôle nommé CustomersBindingNavigator, sont ajoutés au formulaire lié au BindingSource. Celui-ci est à son tour lié à la table Clients dans northwindDataSet.

Tester le formulaire

Vous pouvez maintenant tester le formulaire pour vous assurer qu’il se comporte comme prévu jusqu’à ce stade :

  1. Sélectionnez F5 pour exécuter l’application.

    Le formulaire s’affiche avec un contrôle DataGridView rempli de données de table Clients.

  2. Dans le menu Déboguer, sélectionnez Arrêter le débogage.

Gérer les erreurs d’accès concurrentiel

La façon dont vous gérez les erreurs dépend des règles métier spécifiques qui régissent votre application. Pour ce guide, nous utilisons la stratégie suivante à titre d'exemple pour gérer l’erreur de concurrence.

L’application présente à l’utilisateur trois versions de l’enregistrement :

  • Enregistrement actuel dans la base de données

  • Enregistrement d’origine chargé dans le jeu de données

  • Modifications proposées dans le jeu de données

L’utilisateur peut ensuite remplacer la base de données avec la version proposée, ou annuler la mise à jour et actualiser le jeu de données avec les nouvelles valeurs de la base de données.

Pour activer la gestion des erreurs d’accès concurrentiel

  1. Créez un gestionnaire d’erreurs personnalisé.

  2. Afficher les choix à l’utilisateur.

  3. Traitez la réponse de l’utilisateur.

  4. Renvoyez la mise à jour ou réinitialisez les données dans le jeu de données.

Ajouter du code pour gérer l’exception d’accès concurrentiel

Lorsque vous tentez d’effectuer une mise à jour et qu’une exception est levée, vous souhaitez généralement faire quelque chose avec les informations fournies par l’exception levée. Dans cette section, vous ajoutez du code qui tente de mettre à jour la base de données. Vous gérez également tous les DBConcurrencyException susceptibles d’être déclenchés, ainsi que toutes les autres exceptions.

Remarque

Les méthodes CreateMessage et ProcessDialogResults sont ajoutées ultérieurement dans le guide.

  1. Ajoutez le code suivant sous la Form1_Load méthode :

    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. Remplacez la CustomersBindingNavigatorSaveItem_Click méthode pour appeler la UpdateDatabase méthode afin qu’elle ressemble à ce qui suit :

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

Afficher les choix pour l’utilisateur

Le code que vous venez d’écrire appelle la CreateMessage procédure pour afficher les informations d’erreur à l’utilisateur. Pour cette procédure pas à pas, vous utilisez une boîte de message pour afficher les différentes versions de l’enregistrement à l’utilisateur. Cela permet à l’utilisateur de choisir s’il faut remplacer l’enregistrement avec les modifications ou annuler la modification. Une fois que l’utilisateur sélectionne une option (clique sur un bouton) dans la zone de message, la réponse est transmise à la ProcessDialogResult méthode.

Créez le message en ajoutant le code suivant à l’éditeur de code. Entrez ce code sous la UpdateDatabase méthode :

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

Traiter la réponse de l’utilisateur

Vous avez également besoin de code pour traiter la réponse de l’utilisateur à la boîte de message. Les options sont soit de remplacer l’enregistrement actif dans la base de données avec la modification proposée, soit d’abandonner les modifications locales et d’actualiser la table de données avec l’enregistrement actuellement dans la base de données. Si l’utilisateur choisit Oui, la Merge méthode est appelée avec l’argument preserveChanges défini sur true. Cela entraîne la réussite de la tentative de mise à jour, car la version d’origine de l’enregistrement correspond désormais à l’enregistrement dans la base de données.

Ajoutez le code suivant sous le code ajouté dans la section précédente :

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

Tester le comportement du formulaire

Vous pouvez maintenant tester le formulaire pour vous assurer qu’il se comporte comme prévu. Pour simuler une violation de concurrence, vous modifiez les données de la base de données après avoir rempli NorthwindDataSet.

  1. Sélectionnez F5 pour exécuter l’application.

  2. Une fois le formulaire affiché, laissez-le en cours d’exécution et basculez vers l’IDE Visual Studio.

  3. Dans le menu Affichage , choisissez Explorateur de serveurs.

  4. Dans l’Explorateur de serveurs, développez la connexion que votre application utilise, puis développez le nœud Tables .

  5. Cliquez avec le bouton droit sur la table Customers , puis sélectionnez Afficher les données de table.

  6. Dans le premier enregistrement (ALFKI), remplacez ContactName par Maria Anders2.

    Remarque

    Accédez à une autre ligne pour valider la modification.

  7. Passez au formulaire actif de ConcurrencyWalkthrough.

  8. Dans le premier enregistrement du formulaire (ALFKI), remplacez ContactName par Maria Anders1.

  9. Sélectionnez le bouton Enregistrer.

    L’erreur d’accès concurrentiel est déclenchée et la zone de message s’affiche.

    La sélection de Non annule la mise à jour et met à jour le jeu de données avec les valeurs actuellement dans la base de données. La sélection de Oui écrit la valeur proposée dans la base de données.