Eliminazione batch (VB)

di Scott Mitchell

Scarica il PDF

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.

Ogni riga include una casella di controllo

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.

Copiare il markup dichiarativo di CheckBoxField.aspx negli Appunti

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.

L'interfaccia da CheckBoxField.aspx è stata spostata in BatchDeleting.aspx

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 ProductIDText 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.

I prodotti selezionati verranno eliminati

Figura 4: i prodotti selezionati verranno eliminati (fare clic per visualizzare l'immagine full-size)

I valori ProductID prodotti eliminati sono elencati sotto GridView

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.