Löschen in Batches (VB)
von Scott Mitchell
Erfahren Sie, wie Sie mehrere Datenbankdatensätze in einem einzigen Vorgang löschen. In der Benutzeroberfläche bauen wir auf einer erweiterten GridView auf, die in einem früheren Tutorial erstellt wurde. In der Datenzugriffsebene umschließen wir die mehreren Löschvorgänge innerhalb einer Transaktion, um sicherzustellen, dass alle Löschungen erfolgreich oder alle Löschungen zurückgesetzt werden.
Einführung
Im vorherigen Tutorial wurde das Erstellen einer Batchbearbeitungsschnittstelle mithilfe einer vollständig bearbeitbaren GridView untersucht. In Situationen, in denen Benutzer häufig viele Datensätze gleichzeitig bearbeiten, erfordert eine Batchbearbeitungsschnittstelle viel weniger Postbacks und Kontextwechsel zwischen Tastatur und Maus, wodurch die Effizienz des Endbenutzers verbessert wird. Dieses Verfahren ist ähnlich nützlich für Seiten, auf denen Benutzer häufig viele Datensätze auf einmal löschen.
Jeder, der einen Online-E-Mail-Client verwendet hat, ist bereits mit einer der gängigsten Batchlöschschnittstellen vertraut: ein Kontrollkästchen in jeder Zeile in einem Raster mit einer entsprechenden Schaltfläche Alle überprüften Elemente löschen (siehe Abbildung 1). Dieses Tutorial ist eher kurz, da wir bereits die harte Arbeit in den vorherigen Tutorials beim Erstellen der webbasierten Schnittstelle und einer Methode zum Löschen einer Reihe von Datensätzen als einzelnen atomaren Vorgang ausgeführt haben. Im Tutorial Hinzufügen einer GridView-Spalte von Kontrollkästchen haben wir eine GridView mit einer Spalte von Kontrollkästchen erstellt, und im Tutorial Wrapping Database Modifications in a Transaction haben wir eine Methode in der BLL erstellt, die eine Transaktion zum Löschen von ProductID
Werten List<T>
verwendet. In diesem Tutorial bauen wir auf unseren vorherigen Erfahrungen auf und führen sie zusammen, um ein Beispiel zum Löschen eines funktionierenden Batchs zu erstellen.
Abbildung 1: Jede Zeile enthält ein Kontrollkästchen (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Schritt 1: Erstellen der Batchlöschschnittstelle
Da wir die Batchlöschschnittstelle bereits im Tutorial Hinzufügen einer GridView-Spalte von Kontrollkästchen erstellt haben , können wir sie einfach kopieren, BatchDelete.aspx
anstatt sie von Grund auf neu zu erstellen. Öffnen Sie zunächst die BatchDelete.aspx
Seite im BatchData
Ordner und die CheckBoxField.aspx
Seite im EnhancedGridView
Ordner. Wechseln Sie auf der CheckBoxField.aspx
Seite zur Quellansicht, und kopieren Sie das Markup zwischen den <asp:Content>
Tags, wie in Abbildung 2 gezeigt.
Abbildung 2: Kopieren des deklarativen Markups von CheckBoxField.aspx
in die Zwischenablage (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Wechseln Sie als Nächstes zur Quellansicht, BatchDelete.aspx
und fügen Sie den Inhalt der Zwischenablage in die <asp:Content>
Tags ein. Kopieren Sie außerdem den Code aus der CodeBehind-Klasse inCheckBoxField.aspx.vb
, und fügen Sie ihn innerhalb der CodeBehind-Klasse in BatchDelete.aspx.vb
ein (den DeleteSelectedProducts
Ereignishandler des Button-CodesClick
, die ToggleCheckState
-Methode und die Click
Ereignishandler für die Schaltflächen und UncheckAll
).CheckAll
Nach dem Kopieren dieses Inhalts sollte die BatchDelete.aspx
CodeBehind-Klasse der Seite den folgenden Code enthalten:
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
Nehmen Sie sich nach dem Kopieren des deklarativen Markups und des Quellcodes einen Moment Zeit, um es zu testen BatchDelete.aspx
, indem Sie es über einen Browser anzeigen. Es sollte eine GridView-Liste der ersten zehn Produkte in einer GridView angezeigt werden, wobei jede Zeile den Namen, die Kategorie und den Preis des Produkts sowie ein Kontrollkästchen enthält. Es sollten drei Schaltflächen vorhanden sein: "Alle überprüfen", "Alle" deaktivieren und "Ausgewählte Produkte löschen". Wenn Sie auf die Schaltfläche Alle überprüfen klicken, werden alle Kontrollkästchen aktiviert, während alle Kontrollkästchen deaktiviert werden. Wenn Sie auf Ausgewählte Produkte löschen klicken, wird eine Meldung angezeigt, die die ProductID
Werte der ausgewählten Produkte auflistet, die Produkte jedoch nicht tatsächlich löscht.
Abbildung 3: Die Schnittstelle von CheckBoxField.aspx
wurde nach BatchDeleting.aspx
verschoben (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Schritt 2: Löschen der überprüften Produkte mithilfe von Transaktionen
Nachdem die Batchlöschschnittstelle erfolgreich in BatchDeleting.aspx
kopiert wurde, bleibt nur noch der Code zu aktualisieren, sodass die Schaltfläche Ausgewählte Produkte löschen die überprüften Produkte mithilfe der DeleteProductsWithTransaction
-Methode in der ProductsBLL
-Klasse löscht. Diese Methode, die im Tutorial Wrapping Database Modifications in a Transaction hinzugefügt wurde, akzeptiert als Eingabe a List(Of T)
von ProductID
Werten und löscht jede ProductID
entsprechende innerhalb des Bereichs einer Transaktion.
Der DeleteSelectedProducts
Button-Ereignishandler Click
verwendet derzeit die folgende For Each
Schleife, um jede GridView-Zeile zu durchlaufen:
' 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
Für jede Zeile wird programmgesteuert auf das ProductSelector
CheckBox-Websteuerelement verwiesen. Wenn es aktiviert ist, wird die Zeile s ProductID
aus der DataKeys
Auflistung abgerufen, und die DeleteResults
Eigenschaft der Text
Bezeichnung wird aktualisiert, um eine Meldung zu enthalten, die angibt, dass die Zeile zum Löschen ausgewählt wurde.
Der obige Code löscht keine Datensätze, da der Aufruf der Methode der ProductsBLL
Klasse auskommentiert Delete
wird. Wenn diese Löschlogik angewendet werden soll, würde der Code die Produkte löschen, aber nicht innerhalb eines atomaren Vorgangs. Das heißt, wenn die ersten Löschvorgänge in der Sequenz erfolgreich waren, aber ein späterer Fehler aufgetreten ist (möglicherweise aufgrund einer Verletzung der Fremdschlüsseleinschränkung), würde eine Ausnahme ausgelöst, aber die bereits gelöschten Produkte blieben gelöscht.
Um die Atomität zu gewährleisten, müssen wir stattdessen die Methode s DeleteProductsWithTransaction
der ProductsBLL
Klasse verwenden. Da diese Methode eine Liste von ProductID
Werten akzeptiert, müssen wir diese Liste zuerst aus dem Raster kompilieren und sie dann als Parameter übergeben. Zuerst erstellen wir eine instance vom List(Of T)
Typ Integer
. Innerhalb der For Each
Schleife müssen wir diesem List(Of T)
die ausgewählten Produktwerte ProductID
hinzufügen. Nach der Schleife muss diese List(Of T)
an die Methode der ProductsBLL
Klasse s DeleteProductsWithTransaction
übergeben werden. Aktualisieren Sie den DeleteSelectedProducts
Button-Ereignishandler Click
mit dem folgenden Code:
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
Der aktualisierte Code erstellt einen List(Of T)
vom Typ Integer
(productIDsToDelete
) und füllt es mit den ProductID
zu löschenden Werten auf. Wenn nach der For Each
Schleife mindestens ein Produkt ausgewählt ist, wird die Methode der ProductsBLL
Klasse s DeleteProductsWithTransaction
aufgerufen und diese Liste übergeben. Außerdem DeleteResults
wird die Bezeichnung angezeigt, und die Daten werden an die GridView zurückgegeben (sodass die neu gelöschten Datensätze nicht mehr als Zeilen im Raster angezeigt werden).
Abbildung 4 zeigt die GridView, nachdem eine Reihe von Zeilen zum Löschen ausgewählt wurde. Abbildung 5 zeigt den Bildschirm unmittelbar nach dem Klicken auf die Schaltfläche Ausgewählte Produkte löschen. Beachten Sie, dass in Abbildung 5 die ProductID
Werte der gelöschten Datensätze in der Bezeichnung unterhalb der GridView angezeigt werden und sich diese Zeilen nicht mehr in der GridView befinden.
Abbildung 4: Die ausgewählten Produkte werden gelöscht (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 5: Die Werte für gelöschte Produkte ProductID
werden unter der Rasteransicht aufgeführt (Klicken Sie hier, um das bild in voller Größe anzuzeigen).
Hinweis
Um die Atomität der DeleteProductsWithTransaction
Methode zu testen, fügen Sie manuell einen Eintrag für ein Produkt in der Order Details
Tabelle hinzu, und versuchen Sie dann, dieses Produkt (zusammen mit anderen) zu löschen. Sie erhalten eine Verletzung der Fremdschlüsseleinschränkung, wenn Sie versuchen, das Produkt mit einer zugeordneten Bestellung zu löschen. Beachten Sie jedoch, wie die löschungen der anderen ausgewählten Produkte zurückgesetzt werden.
Zusammenfassung
Beim Erstellen einer Batchlöschschnittstelle wird eine GridView mit einer Spalte mit Kontrollkästchen und ein Button-Websteuerelement hinzugefügt, das beim Klicken alle ausgewählten Zeilen als einzelnen atomaren Vorgang löscht. In diesem Tutorial haben wir eine solche Schnittstelle erstellt, indem wir die Arbeit in zwei vorherigen Tutorials zusammenarbeiten: Hinzufügen einer GridView-Spalte mit Kontrollkästchen und Umschließen von Datenbankänderungen innerhalb einer Transaktion. Im ersten Tutorial haben wir eine GridView mit einer Spalte von Kontrollkästchen erstellt, und in letzterem haben wir eine Methode in der BLL implementiert, die, wenn ein List(Of T)
von ProductID
Werten übergeben wurde, alle innerhalb des Bereichs einer Transaktion gelöscht hat.
Im nächsten Tutorial erstellen wir eine Schnittstelle zum Ausführen von Batcheinfügungen.
Viel Spaß beim Programmieren!
Zum Autor
Scott Mitchell, Autor von sieben ASP/ASP.NET-Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.
Besonderen Dank an
Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Leitende Gutachter für dieses Tutorial waren Hilton Giesenow und Teresa Murphy. Möchten Sie meine anstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.