Procédure pas à pas : gestion d'une exception d'accès concurrentiel
Date de publication : mars 2016
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 :
Créez un nouveau projet Application Windows.
Créez un nouveau groupe de données basé sur la table
Customers
Northwind.Créez un formulaire avec un DataGridView pour afficher les données.
Remplissez un groupe de données avec les données provenant de la table
Customers
de la base de données Northwind.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.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.
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 :
- avoir accès à l'exemple de base de données Northwind avec l'autorisation d'effectuer des mises à jour. Pour plus d'informations, consultez Comment : installer des exemples de bases de données.
Notes
Les boîtes de dialogue et les commandes de menu qui s'affichent peuvent être différentes de celles qui sont décrites dans l'aide, en fonction de vos paramètres actifs ou de l'édition utilisée. Pour modifier vos paramètres, choisissez Importation et exportation de paramètres dans le menu Outils. Pour plus d'informations, consultez Customizing Development Settings in 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
Dans le menu Fichier, créez un nouveau projet.
Sélectionnez un langage de programmation dans le volet Types de projets.
Sélectionnez Application Windows dans le volet Modèles.
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
Dans le menu Données, choisissez Ajouter une nouvelle source de données.
Sélectionnez Base de données dans la page Choisir un type de source de données.
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.
Notes
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.
Cliquez sur Suivant dans la page Enregistrer la chaîne de connexion dans le fichier de configuration de l'application.
Développez le nœud Tables et sélectionnez la table
Customers
. Le nom par défaut du groupe de données doit êtreNorthwindDataSet
.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
Dans le menu Données, choisissez Afficher les sources de données pour ouvrir la fenêtre Sources de données.
Dans la fenêtre Sources de données, développez le nœud NorthwindDataSet et sélectionnez la table Customers.
Cliquez sur la flèche vers le bas du nœud de la table et sélectionnez DataGridView dans la liste déroulante.
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 tableCustomers
contenue dans leNorthwindDataSet
.
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
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
.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
Créez un gestionnaire d'erreurs personnalisé.
Affichez des choix pour l'utilisateur.
Traitez la réponse de l'utilisateur.
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.
Notes
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
Ajoutez le code suivant sous la méthode
Form1_Load
: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."); } }
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
Remplacez la méthode
CustomersBindingNavigatorSaveItem_Click
pour appeler la méthodeUpdateDatabase
pour obtenir le code suivant :private void customersBindingNavigatorSaveItem_Click(object sender, EventArgs e) { UpdateDatabase(); }
Private Sub CustomersBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CustomersBindingNavigatorSaveItem.Click UpdateDatabase() End Sub
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 la boîte de 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 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; }
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
Traitement de la réponse de l'utilisateur
Vous devrez également ajouter du code pour le traitement de la réponse de l'utilisateur à la boîte de 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 à 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 à la boîte de 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 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; } }
' 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
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
Appuyez sur la touche F5 pour exécuter l’application.
Une fois le formulaire affiché, laissez-le s'exécuter et basculez vers l'environnement IDE Visual Studio.
Dans le menu Affichage, choisissez Explorateur de serveurs.
Dans l'Explorateur de serveurs, développez la connexion que votre application utilise, puis développez le nœud Tables.
Cliquez avec le bouton droit sur la table Customers et sélectionnez Afficher les données de la table.
Dans le premier enregistrement (
ALFKI
), remplacezContactName
parMaria Anders2
.Notes
Naviguez vers une autre ligne pour valider la modification.
Basculez vers le formulaire en cours d'exécution de
ConcurrencyWalkthrough
.Dans le premier enregistrement du formulaire (
ALFKI
), remplacezContactName
parMaria Anders1
.Cliquez sur le bouton Enregistrer.
L'erreur d'accès concurrentiel est déclenchée et la boîte de message apparaît.
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
Procédures pas à pas relatives aux données
Liaison de contrôles Windows Forms à des données dans Visual Studio
Connexion aux données dans Visual Studio
Préparation de votre application pour recevoir des données
Extraction de données dans votre application
Liaison de contrôles à des données dans Visual Studio
Modification des données dans votre application
Validation des données
Enregistrement des données