Procédure pas à pas : gestion d'une exception d'accès concurrentiel

Mise à jour : novembre 2007

Des exceptions d'accès concurrentiel (DBConcurrencyException) sont levées lorsque deux utilisateurs tentent de modifier simultanément les mêmes données dans une base de données. Dans le cadre de cette procédure pas à pas, vous allez créer une application Windows qui illustre l'interception d'une exception DBConcurrencyException, la recherche de la ligne ayant provoqué l'erreur et le choix d'une stratégie pour la traiter.

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

  1. Créez un nouveau projet Application Windows.

  2. Créez un nouveau groupe de données basé sur la table Customers Northwind.

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

  4. Remplissez un groupe de données avec les données provenant de la table Customers de la base de données Northwind.

  5. Une fois le groupe de données rempli, utilisez Visual Database Tools dans Visual Studio pour accéder directement à la table de données Customers et modifier un enregistrement.

  6. Ensuite, modifiez la valeur de cet enregistrement sur le formulaire, mettez à jour le groupe de données et essayez d'enregistrer les modifications dans la base de données, ce qui entraîne le déclenchement d'une erreur d'accès concurrentiel.

  7. Détectez l'erreur, puis affichez les différentes versions de l'enregistrement, permettant ainsi à l'utilisateur de déterminer s'il doit continuer à mettre à jour la base de données ou annuler la mise à jour.

Composants requis

Pour exécuter cette procédure pas à pas, vous devez utiliser :

Remarque :

Les boîtes de dialogue et les commandes de menu que vous voyez peuvent différer de celles qui sont décrites dans l'aide selon vos paramètres actifs ou votre édition. Pour modifier vos paramètres, choisissez Importation et exportation de paramètres dans le menu Outils. Pour plus d'informations, consultez Paramètres Visual Studio.

Création d'un projet

La première étape de la procédure consiste à créer une nouvelle application Windows.

Pour créer un projet d'application Windows

  1. Dans le menu Fichier, créez un nouveau projet.

  2. Sélectionnez un langage de programmation dans le volet Types de projets.

  3. Sélectionnez Application Windows dans le volet Modèles.

  4. Nommez le projet ConcurrencyWalkthrough, puis cliquez sur OK.

    Visual Studio ajoute le projet à l'Explorateur de solutions et affiche un nouveau formulaire dans le concepteur.

Création du groupe de données Northwind

Dans cette section, vous allez créer un groupe de données nommé NorthwindDataSet.

Pour créer 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. Sélectionnez Base de données dans la page Choisir un type de source de données.

  3. Sélectionnez une connexion à l'exemple de base de données Northwind dans la liste des connexions disponibles, ou cliquez sur Nouvelle connexion si la connexion ne figure pas dans la liste.

    Remarque :

    Si vous vous connectez à un fichier de base de données local, sélectionnez Non lorsque vous êtes invité à spécifier si vous souhaitez ajouter le fichier à votre projet.

  4. Cliquez sur Suivant dans la page Enregistrer la chaîne de connexion dans le fichier de configuration de l'application.

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

  6. Cliquez sur Terminer pour ajouter le groupe de données au projet.

Création d'un contrôle DataGridView lié aux données

Dans cette section, vous créerez un DataGridView en faisant glisser l'élément Customers depuis la fenêtre Sources de données jusqu'à votre Windows Form.

Créer un contrôle DataGridView lié à la table Customers

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

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

  3. Cliquez sur la flèche vers le bas du nœud de la table et sélectionnez DataGridView dans la liste déroulante.

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

    Un contrôle DataGridView nommé CustomersDataGridView et un BindingNavigator nommé CustomersBindingNavigator sont ajoutés au formulaire lié au BindingSource qui est lui-même lié à la table Customers contenue dans le NorthwindDataSet.

Point de contrôle

Vous pouvez à présent tester le formulaire afin de vous assurer qu'il se comporte comme prévu jusqu'à ce point.

Pour tester le formulaire

  1. Appuyez sur F5 pour exécuter l'application.

    Le formulaire s'affiche avec un contrôle DataGridView rempli des données de la table Customers.

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

Gestion des erreurs d'accès concurrentiel

La façon dont vous gérez les erreurs dépend des règles spécifiques à votre entreprise, qui gèrent votre application. Dans le cadre de cette procédure pas à pas, après déclenchement d'une violation d'accès concurrentiel, la stratégie suivante est utilisée pour illustrer la gestion de l'erreur d'accès concurrentiel :

L'application présentera à l'utilisateur trois versions de l'enregistrement :

  • L'enregistrement en cours dans la base de données.

  • L'enregistrement d'origine chargé dans le groupe de données.

  • Les modifications proposées dans le groupe de données.

L'utilisateur peut alors remplacer la base de données par la version proposée ou annuler la mise à jour et l'actualisation du groupe 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. Affichez des choix pour l'utilisateur.

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

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

Ajout du code permettant de gérer l'exception d'accès concurrentiel

Si une exception est levée lorsque vous essayez d'exécuter une mise à jour, vous souhaiterez généralement vous servir des informations qu'elle fournit.

Dans cette section, vous ajouterez le code qui tentera de mettre à jour la base de données et de gérer toute exception DBConcurrencyException susceptible d'être levée, ainsi que toute autre exception.

Remarque :

Les méthodes CreateMessage et ProcessDialogResults seront ajoutées à une étape ultérieure de cette procédure.

Pour ajouter la gestion des erreurs pour l'erreur d'accès concurrentiel

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

    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. Remplacez la méthode CustomersBindingNavigatorSaveItem_Click pour appeler la méthode UpdateDatabase pour obtenir le code suivant :

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

Affichage des choix pour l'utilisateur

Le code que vous venez de taper appelle la procédure CreateMessage qui va afficher les informations sur l'erreur pour l'utilisateur. Dans cette procédure, vous utiliserez une boîte de message pour afficher les différentes versions de l'enregistrement pour l'utilisateur et lui permettre de choisir entre le remplacement de l'enregistrement avec les modifications et l'annulation des modifications. Lorsque l'utilisateur sélectionne une option (clique sur un bouton) dans le message, la réponse est passée à la méthode ProcessDialogResult.

Pour créer le message à afficher pour l'utilisateur

  • Créez le message en ajoutant le code ci-dessous dans l'éditeur de code. Entrez ce code sous la méthode UpdateDatabase.

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

Traitement de la réponse de l'utilisateur

Vous devrez également ajouter du code pour le traitement de la réponse de l'utilisateur au message. Vous pouvez choisir de remplacer l'enregistrement actuel dans la base de données par la modification proposée ou d'abandonner les modifications locales et actualiser la table de données avec l'enregistrement qui se trouve actuellement dans la base de données. Si l'utilisateur choisit Oui, la méthode Merge est appelée avec l'argument preserveChanges ayant la valeur true. La mise à jour fonctionnera alors correctement, car la version d'origine de l'enregistrement correspond désormais à l'enregistrement contenu dans la base de données.

Pour traiter la réponse de l'utilisateur au message

  • Ajoutez le code suivant sous le code ajouté à 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 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;
        }
    }
    

Test

Vous pouvez à présent tester le formulaire afin de vous assurer qu'il se comporte comme prévu. Pour simuler une violation de l'accès concurrentiel, vous devez modifier les données dans la base de données après avoir rempli le NorthwindDataSet.

Pour tester le formulaire

  1. Appuyez sur F5 pour exécuter l'application.

  2. Une fois le formulaire affiché, laissez-le s'exécuter et basculez vers l'environnement 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 et sélectionnez Afficher les données de la table.

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

    Remarque :

    Naviguez vers une autre ligne pour valider la modification.

  7. Basculez vers le formulaire en cours d'exécution de ConcurrencyWalkthrough.

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

  9. Cliquez sur le bouton Enregistrer.

    L'erreur d'accès concurrentiel est déclenchée et le message apparaît.

  10. Cliquez sur Non pour annuler la mise à jour et mettre à jour le groupe de données avec les valeurs actuellement contenues dans la base de données, ou cliquez sur Oui pour écrire la valeur proposée dans la base de données.

Voir aussi

Concepts

Nouveautés des données

Vue d'ensemble de l'affichage des données

Autres ressources

Procédures pas à pas relatives aux données

Connexion aux données dans Visual Studio

Préparation de votre application pour recevoir des données

Extraction de données dans votre application

Affichage des données sur des formulaires dans les applications Windows

Modification des données dans votre application

Validation des données

Enregistrement des données