Eliminazione batch (VB)
Informazioni su come eliminare più record di database in una singola operazione. Nel livello interfaccia utente si basa su un'esercitazione gridView migliorata creata in un'esercitazione precedente. Nel livello di accesso ai dati vengono eseguito il rollback di più operazioni di eliminazione all'interno di una transazione per garantire che tutte le eliminazioni abbiano esito positivo o tutte le eliminazioni.
Introduzione
L'esercitazione precedente ha illustrato come creare un'interfaccia di modifica batch usando GridView completamente modificabile. In situazioni in cui gli utenti modificano comunemente molti record contemporaneamente, un'interfaccia di modifica batch richiederà molto meno postback e commutatori di contesto da tastiera a mouse, migliorando così l'efficienza dell'utente finale. Questa tecnica è analogamente utile per le pagine in cui è comune per gli utenti eliminare molti record in un'unica operazione.
Chiunque abbia usato un client di posta elettronica online ha già familiarità con una delle interfacce di eliminazione batch più comuni: una casella di controllo in ogni riga in una griglia con un pulsante Elimina tutti gli elementi controllati corrispondente (vedere la figura 1). Questa esercitazione è piuttosto breve perché abbiamo già fatto tutto il duro lavoro nelle esercitazioni precedenti nella creazione sia dell'interfaccia basata sul Web che di un metodo per eliminare una serie di record come singola operazione atomica. Nell'esercitazione Aggiunta di una colonna GridView delle caselle di controllo è stata creata una casella di controllo GridView con una colonna di caselle di controllo e nell'esercitazione Wrapping delle modifiche del database all'interno di un'esercitazione Sulle transazioni è stato creato un metodo nel BLL che userebbe una transazione per eliminare un List<T>
valore ProductID
. In questa esercitazione si creerà e si uniranno le esperienze precedenti per creare un esempio di eliminazione batch funzionante.
Figura 1: Ogni riga include una casella di controllo (fare clic per visualizzare l'immagine full-size)
Passaggio 1: Creazione dell'interfaccia di eliminazione batch
Poiché è già stata creata l'interfaccia di eliminazione batch nell'esercitazione Aggiunta di una colonna GridView delle caselle di controllo, è sufficiente copiarla in BatchDelete.aspx
anziché crearla da zero. Iniziare aprendo la BatchDelete.aspx
pagina nella BatchData
cartella e nella CheckBoxField.aspx
pagina nella EnhancedGridView
cartella. CheckBoxField.aspx
Nella pagina passare alla visualizzazione Origine e copiare il markup tra i <asp:Content>
tag, come illustrato nella figura 2.
Figura 2: Copiare il markup dichiarativo degli CheckBoxField.aspx
Appunti (fare clic per visualizzare l'immagine a dimensioni complete)
Passare quindi alla visualizzazione Origine in BatchDelete.aspx
e incollare il contenuto degli Appunti all'interno dei <asp:Content>
tag. Copiare e incollare anche il codice dall'interno della classe code-behind all'interno CheckBoxField.aspx.vb
della classe code-behind in BatchDelete.aspx.vb
(gestore DeleteSelectedProducts
eventi Button s Click
, il ToggleCheckState
metodo e i Click
gestori eventi per i CheckAll
pulsanti e UncheckAll
). Dopo aver copiato su questo contenuto, la BatchDelete.aspx
classe code-behind della pagina deve contenere il codice seguente:
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
Dopo aver copiato il markup dichiarativo e il codice sorgente, eseguire un test BatchDelete.aspx
visualizzandolo tramite un browser. Verrà visualizzato un elenco gridView dei primi dieci prodotti in gridView con ogni riga che elenca il nome, la categoria e il prezzo del prodotto insieme a una casella di controllo. Dovrebbero essere presenti tre pulsanti: Controlla tutto, Deseleziona tutto e Elimina prodotti selezionati. Facendo clic sul pulsante Controlla tutto selezionare tutte le caselle di controllo, mentre Deseleziona tutte le caselle di controllo Deseleziona tutte. Facendo clic su Elimina prodotti selezionati viene visualizzato un messaggio che elenca i ProductID
valori dei prodotti selezionati, ma non elimina effettivamente i prodotti.
Figura 3: l'interfaccia da CheckBoxField.aspx
è stata spostata in BatchDeleting.aspx
(Fare clic per visualizzare l'immagine a dimensioni complete)
Passaggio 2: Eliminazione dei prodotti controllati tramite transazioni
Con l'interfaccia di eliminazione batch copiata correttamente in BatchDeleting.aspx
, tutto ciò che rimane consiste nell'aggiornare il codice in modo che il pulsante Delete Selected Products elimina i prodotti controllati usando il DeleteProductsWithTransaction
metodo nella ProductsBLL
classe. Questo metodo, aggiunto nell'esercitazione Di wrapping delle modifiche al database all'interno di una transazione, accetta come input un List(Of T)
valore di ProductID
valori ed elimina ogni corrispondente ProductID
nell'ambito di una transazione.
Il DeleteSelectedProducts
gestore eventi Button Click
usa attualmente il ciclo seguente For Each
per eseguire l'iterazione di ogni riga 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
Per ogni riga, viene fatto riferimento al ProductSelector
controllo Web CheckBox a livello di codice. Se è selezionata, la riga viene recuperata dall'insieme DataKeys
e la DeleteResults
proprietà Label s ProductID
Text
viene aggiornata per includere un messaggio che indica che la riga è stata selezionata per l'eliminazione.
Il codice precedente non elimina effettivamente i record perché la chiamata al ProductsBLL
metodo della Delete
classe viene commentata. Se questa logica di eliminazione deve essere applicata, il codice eliminerebbe i prodotti ma non all'interno di un'operazione atomica. Ovvero, se le prime eliminazioni nella sequenza hanno avuto esito positivo, ma una successiva operazione ha avuto esito negativo (forse a causa di una violazione del vincolo di chiave esterna), verrà generata un'eccezione ma tali prodotti già eliminati rimarranno eliminati.
Per garantire l'atomicità, è invece necessario usare il ProductsBLL
metodo della DeleteProductsWithTransaction
classe. Poiché questo metodo accetta un elenco di ProductID
valori, è necessario prima compilare questo elenco dalla griglia e quindi passarlo come parametro. Per prima cosa viene creata un'istanza di un List(Of T)
tipo Integer
. All'interno del For Each
ciclo è necessario aggiungere i valori dei prodotti ProductID
selezionati a questo List(Of T)
oggetto . Dopo aver passato il ciclo List(Of T)
al ProductsBLL
metodo della DeleteProductsWithTransaction
classe. Aggiornare il DeleteSelectedProducts
gestore eventi button con Click
il codice seguente:
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
Il codice aggiornato crea un List(Of T)
tipo Integer
(productIDsToDelete
) e lo popola con i ProductID
valori da eliminare. Dopo il For Each
ciclo, se è selezionato almeno un prodotto, il ProductsBLL
metodo della DeleteProductsWithTransaction
classe viene chiamato e passato questo elenco. L'etichetta DeleteResults
viene visualizzata anche e i dati vengono inseriti in GridView (in modo che i record appena eliminati non vengano più visualizzati come righe nella griglia).
La figura 4 mostra GridView dopo aver selezionato un numero di righe per l'eliminazione. La figura 5 mostra la schermata immediatamente dopo aver fatto clic sul pulsante Elimina prodotti selezionati. Si noti che nella figura 5 i ProductID
valori dei record eliminati vengono visualizzati nell'etichetta sotto GridView e tali righe non sono più presenti in GridView.
Figura 4: i prodotti selezionati verranno eliminati (fare clic per visualizzare l'immagine full-size)
Figura 5: i valori dei prodotti ProductID
eliminati sono elencati sotto GridView (Fare clic per visualizzare l'immagine a dimensioni complete)
Nota
Per testare l'atomicità DeleteProductsWithTransaction
del metodo, aggiungere manualmente una voce per un prodotto nella Order Details
tabella e quindi tentare di eliminare tale prodotto (insieme ad altri). Si riceverà una violazione del vincolo di chiave esterna quando si tenta di eliminare il prodotto con un ordine associato, ma si noti come vengono rollback le altre eliminazioni di prodotti selezionati.
Riepilogo
La creazione di un'interfaccia di eliminazione batch comporta l'aggiunta di un controllo GridView con una colonna di caselle di controllo e un controllo Web Button che, quando è stato fatto clic, eliminerà tutte le righe selezionate come singola operazione atomica. In questa esercitazione è stata creata un'interfaccia di questo tipo grazie al lavoro eseguito insieme in due esercitazioni precedenti, l'aggiunta di una colonna GridView delle caselle di controllo e il wrapping delle modifiche al database all'interno di una transazione. Nella prima esercitazione è stata creata una funzione GridView con una colonna di caselle di controllo e in quest'ultima è stato implementato un metodo nel BLL che, quando è stato passato un List(Of T)
valore ProductID
, li ha eliminati tutti all'interno dell'ambito di una transazione.
Nell'esercitazione successiva verrà creata un'interfaccia per l'esecuzione di inserimenti batch.
Programmazione felice!
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Microsoft Web dal 1998. Scott lavora come consulente indipendente, allenatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2,0 in 24 Ore. Può essere raggiunto a mitchell@4GuysFromRolla.com. o tramite il suo blog, che può essere trovato in http://ScottOnWriting.NET.
Grazie speciali
Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali per questa esercitazione sono stati Hilton Giesenow e Teresa Murphy. Interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami una riga in mitchell@4GuysFromRolla.com.