Suppression par lots (VB)
par Scott Mitchell
Découvrez comment supprimer plusieurs enregistrements de base de données en une seule opération. Dans la couche d’interface utilisateur, nous nous appuyons sur un GridView amélioré créé dans un tutoriel précédent. Dans la couche d’accès aux données, nous encapsulons les plusieurs opérations de suppression au sein d’une transaction pour nous assurer que toutes les suppressions réussissent ou que toutes les suppressions sont restaurées.
Introduction
Le tutoriel précédent a exploré comment créer une interface d’édition par lots à l’aide d’un GridView entièrement modifiable. Dans les situations où les utilisateurs modifient généralement de nombreux enregistrements à la fois, une interface d’édition par lots nécessite beaucoup moins de publications et de commutateurs de contexte de clavier à souris, ce qui améliore l’efficacité de l’utilisateur final. Cette technique est également utile pour les pages où il est courant pour les utilisateurs de supprimer de nombreux enregistrements en une seule fois.
Toute personne ayant utilisé un client de messagerie en ligne est déjà familiarisée avec l’une des interfaces de suppression par lots les plus courantes : une case à cocher dans chaque ligne d’une grille avec un bouton Supprimer tous les éléments vérifiés correspondant (voir figure 1). Ce tutoriel est assez court, car nous avons déjà effectué tout le travail acharné des tutoriels précédents en créant à la fois l’interface web et une méthode pour supprimer une série d’enregistrements en tant qu’opération atomique unique. Dans le didacticiel Ajout d’une colonne GridView de cases à cocher , nous avons créé un GridView avec une colonne de cases à cocher et, dans le didacticiel Wrapping Database Modifications dans un transaction , nous avons créé une méthode dans le BLL qui utiliserait une transaction pour supprimer un List<T>
de ProductID
valeurs. Dans ce tutoriel, nous allons nous appuyer sur nos expériences précédentes et les fusionner pour créer un exemple de suppression par lots de travail.
Figure 1 : Chaque ligne inclut une case à cocher (cliquer pour afficher l’image en taille réelle)
Étape 1 : Création de l’interface de suppression de lot
Étant donné que nous avons déjà créé l’interface de suppression par lots dans le didacticiel Ajout d’une colonne GridView de cases à cocher , nous pouvons simplement la copier vers plutôt que de la créer à BatchDelete.aspx
partir de zéro. Commencez par ouvrir la BatchDelete.aspx
page dans le BatchData
dossier et la CheckBoxField.aspx
page dans le EnhancedGridView
dossier. Dans la CheckBoxField.aspx
page, accédez à la vue Source et copiez le balisage entre les balises, comme illustré dans la <asp:Content>
figure 2.
Figure 2 : Copier le balisage déclaratif de CheckBoxField.aspx
dans le Presse-papiers (cliquer pour afficher l’image en taille réelle)
Ensuite, accédez à la vue Source dans BatchDelete.aspx
et collez le contenu du Presse-papiers dans les <asp:Content>
balises. Copiez et collez également le code à partir de la classe code-behind dans CheckBoxField.aspx.vb
vers dans la classe code-behind dans BatchDelete.aspx.vb
(le DeleteSelectedProducts
gestionnaire d’événements Click
Button, la ToggleCheckState
méthode et les Click
gestionnaires d’événements pour les CheckAll
boutons et UncheckAll
). Après avoir copié ce contenu, la classe code-behind de la BatchDelete.aspx
page doit contenir le code suivant :
Partial Class BatchData_BatchDelete
Inherits System.Web.UI.Page
Protected Sub DeleteSelectedProducts_Click(sender As Object, e As EventArgs) _
Handles DeleteSelectedProducts.Click
Dim atLeastOneRowDeleted As Boolean = False
' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
' Access the CheckBox
Dim cb As CheckBox = row.FindControl("ProductSelector")
If cb IsNot Nothing AndAlso cb.Checked Then
' Delete row! (Well, not really...)
atLeastOneRowDeleted = True
' First, get the ProductID for the selected row
Dim productID As Integer = _
Convert.ToInt32(Products.DataKeys(row.RowIndex).Value)
' "Delete" the row
DeleteResults.Text &= String.Format _
("This would have deleted ProductID {0}<br />", productID)
'... To actually delete the product, use ...
' Dim productAPI As New ProductsBLL
' productAPI.DeleteProduct(productID)
'............................................
End If
Next
' Show the Label if at least one row was deleted...
DeleteResults.Visible = atLeastOneRowDeleted
End Sub
Private Sub ToggleCheckState(ByVal checkState As Boolean)
' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
' Access the CheckBox
Dim cb As CheckBox = row.FindControl("ProductSelector")
If cb IsNot Nothing Then
cb.Checked = checkState
End If
Next
End Sub
Protected Sub CheckAll_Click(sender As Object, e As EventArgs) _
Handles CheckAll.Click
ToggleCheckState(True)
End Sub
Protected Sub UncheckAll_Click(sender As Object, e As EventArgs) _
Handles UncheckAll.Click
ToggleCheckState(False)
End Sub
End Class
Après avoir copié le balisage déclaratif et le code source, prenez un moment pour le tester BatchDelete.aspx
en l’affichant via un navigateur. Vous devriez voir un GridView répertoriant les dix premiers produits dans un GridView avec chaque ligne indiquant le nom, la catégorie et le prix du produit, ainsi qu’une case à cocher. Il doit y avoir trois boutons : Vérifier tout, Désactiver tout et Supprimer les produits sélectionnés. Le fait de cliquer sur le bouton Vérifier tout permet de cocher toutes les cases à cocher, tandis que La case Désactiver tout désactive toutes les cases. Cliquer sur Supprimer les produits sélectionnés affiche un message qui répertorie les ProductID
valeurs des produits sélectionnés, mais ne supprime pas réellement les produits.
Figure 3 : L’interface de CheckBoxField.aspx
a été déplacée vers BatchDeleting.aspx
(Cliquer pour afficher l’image en taille réelle)
Étape 2 : Suppression des produits vérifiés à l’aide de transactions
Une fois l’interface de suppression par lots correctement copiée dans BatchDeleting.aspx
, il ne reste plus qu’à mettre à jour le code afin que le bouton Supprimer les produits sélectionnés supprime les produits vérifiés à l’aide de la DeleteProductsWithTransaction
méthode dans la ProductsBLL
classe . Cette méthode, ajoutée dans le didacticiel Wrapping Database Modifications dans un didacticiel Transaction , accepte comme entrée a List(Of T)
de ProductID
valeurs et supprime chacune correspondant ProductID
dans l’étendue d’une transaction.
Le DeleteSelectedProducts
gestionnaire d’événements Button Click
utilise actuellement la boucle suivante For Each
pour itérer sur chaque ligne GridView :
' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
' Access the CheckBox
Dim cb As CheckBox = row.FindControl("ProductSelector")
If cb IsNot Nothing AndAlso cb.Checked Then
' Delete row! (Well, not really...)
atLeastOneRowDeleted = True
' First, get the ProductID for the selected row
Dim productID As Integer = _
Convert.ToInt32(Products.DataKeys(row.RowIndex).Value)
' "Delete" the row
DeleteResults.Text &= String.Format _
("This would have deleted ProductID {0}<br />", productID)
'... To actually delete the product, use ...
' Dim productAPI As New ProductsBLL
' productAPI.DeleteProduct(productID)
'............................................
End If
Next
Pour chaque ligne, le ProductSelector
contrôle Web CheckBox est référencé par programmation. Si elle est cochée, la ligne s ProductID
est récupérée à partir de la DataKeys
collection et la DeleteResults
propriété Label s Text
est mise à jour pour inclure un message indiquant que la ligne a été sélectionnée pour suppression.
Le code ci-dessus ne supprime pas réellement d’enregistrements, car l’appel à la méthode s de classe ProductsBLL
est Delete
commenté. Si cette logique de suppression devait être appliquée, le code supprimerait les produits, mais pas dans une opération atomique. Autrement dit, si les premières suppressions de la séquence ont réussi, mais qu’une autre a échoué (peut-être en raison d’une violation de contrainte de clé étrangère), une exception serait levée, mais ces produits déjà supprimés resteraient supprimés.
Pour garantir l’atomicité, nous devons plutôt utiliser la méthode de classe ProductsBLL
s DeleteProductsWithTransaction
. Étant donné que cette méthode accepte une liste de ProductID
valeurs, nous devons d’abord compiler cette liste à partir de la grille, puis la transmettre en tant que paramètre. Nous créons d’abord un instance d’un List(Of T)
de type Integer
. Dans la For Each
boucle, nous devons ajouter les valeurs de produits ProductID
sélectionnées à ce List(Of T)
. Après la boucle, cela List(Of T)
doit être passé à la ProductsBLL
méthode class s DeleteProductsWithTransaction
. Mettez à jour le DeleteSelectedProducts
gestionnaire d’événements Button Click
avec le code suivant :
Protected Sub DeleteSelectedProducts_Click(sender As Object, e As EventArgs) _
Handles DeleteSelectedProducts.Click
' Create a List to hold the ProductID values to delete
Dim productIDsToDelete As New System.Collections.Generic.List(Of Integer)
' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
' Access the CheckBox
Dim cb As CheckBox = CType(row.FindControl("ProductSelector"), CheckBox)
If cb IsNot Nothing AndAlso cb.Checked Then
' Save the ProductID value for deletion
' First, get the ProductID for the selected row
Dim productID As Integer = _
Convert.ToInt32(Products.DataKeys(row.RowIndex).Value)
' Add it to the List...
productIDsToDelete.Add(productID)
' Add a confirmation message
DeleteResults.Text &= String.Format _
("ProductID {0} has been deleted<br />", productID)
End If
Next
' Call the DeleteProductsWithTransaction method and show the Label
' if at least one row was deleted...
If productIDsToDelete.Count > 0 Then
Dim productAPI As New ProductsBLL()
productAPI.DeleteProductsWithTransaction(productIDsToDelete)
DeleteResults.Visible = True
' Rebind the data to the GridView
Products.DataBind()
End If
End Sub
Le code mis à jour crée un List(Of T)
de type Integer
(productIDsToDelete
) et le remplit avec les ProductID
valeurs à supprimer. Après la For Each
boucle, si au moins un produit est sélectionné, la ProductsBLL
méthode class s DeleteProductsWithTransaction
est appelée et a passé cette liste. L’étiquette DeleteResults
est également affichée et les données rebondissent vers GridView (de sorte que les enregistrements récemment supprimés n’apparaissent plus sous forme de lignes dans la grille).
La figure 4 montre gridView une fois qu’un certain nombre de lignes ont été sélectionnées pour suppression. La figure 5 montre l’écran immédiatement après que vous avez cliqué sur le bouton Supprimer les produits sélectionnés. Notez que dans la figure 5, les ProductID
valeurs des enregistrements supprimés sont affichées dans l’étiquette sous GridView et que ces lignes ne se trouvent plus dans gridView.
Figure 4 : Les produits sélectionnés seront supprimés (cliquez pour afficher l’image en taille réelle)
Figure 5 : Les valeurs des produits ProductID
supprimés sont répertoriées sous gridView (cliquer pour afficher l’image en taille réelle)
Notes
Pour tester l’atomicité de la DeleteProductsWithTransaction
méthode, ajoutez manuellement une entrée pour un produit dans la Order Details
table, puis tentez de supprimer ce produit (avec d’autres). Vous recevrez une violation de contrainte de clé étrangère lorsque vous tentez de supprimer le produit avec une commande associée, mais notez comment les autres suppressions de produits sélectionnés sont annulées.
Résumé
La création d’une interface de suppression par lots implique l’ajout d’un GridView avec une colonne de cases à cocher et d’un contrôle Web Button qui, en cas de clic, supprime toutes les lignes sélectionnées en tant qu’opération atomique unique. Dans ce tutoriel, nous avons créé une telle interface en regroupant le travail effectué dans deux didacticiels précédents, ajout d’une colonne GridView de cases à cocher et habillage des modifications de base de données dans une transaction. Dans le premier tutoriel, nous avons créé un GridView avec une colonne de cases à cocher et dans ce dernier, nous avons implémenté une méthode dans le BLL qui, lors de la transmission d’un List(Of T)
de ProductID
valeurs, les a supprimées toutes dans l’étendue d’une transaction.
Dans le tutoriel suivant, nous allons créer une interface pour effectuer des insertions par lots.
Bonne programmation !
À propos de l’auteur
Scott Mitchell, auteur de sept livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies Web Microsoft depuis 1998. Scott travaille comme consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 in 24 Heures. Il est accessible à l’adressemitchell@4GuysFromRolla.com . ou via son blog, qui peut être trouvé à l’adresse http://ScottOnWriting.NET.
Un merci spécial à
Cette série de tutoriels a été examinée par de nombreux réviseurs utiles. Les principaux réviseurs de ce tutoriel étaient Hilton Giesenow et Teresa Murphy. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.