Esecuzione di aggiornamenti batch (VB)

di Scott Mitchell

Scarica il PDF

Informazioni su come creare un oggetto DataList completamente modificabile in cui tutti gli elementi sono in modalità di modifica e i cui valori possono essere salvati facendo clic su un pulsante "Aggiorna tutto" nella pagina.

Introduzione

Nell'esercitazione precedente è stato esaminato come creare un oggetto DataList a livello di elemento. Analogamente a GridView modificabile standard, ogni elemento in DataList includeva un pulsante Modifica che, quando si fa clic, renderebbe modificabile l'elemento. Sebbene questa modifica a livello di elemento funzioni correttamente per i dati aggiornati solo occasionalmente, alcuni scenari di caso d'uso richiedono all'utente di modificare molti record. Se un utente deve modificare decine di record ed è costretto a fare clic su Modifica, apportare le modifiche e fare clic su Aggiorna per ognuno di essi, la quantità di clic può impedire la produttività. In tali situazioni, un'opzione migliore consiste nel fornire un oggetto DataList completamente modificabile, uno in cui tutti gli elementi sono in modalità di modifica e i cui valori possono essere modificati facendo clic su un pulsante Aggiorna tutto nella pagina (vedere la figura 1).

Ogni elemento in un elenco di dati modificabile completamente può essere modificato

Figura 1: ogni elemento in un elenco di dati completamente modificabile può essere modificato (fare clic per visualizzare l'immagine full-size)

In questa esercitazione verrà illustrato come consentire agli utenti di aggiornare le informazioni sugli indirizzi dei fornitori usando un DataList completamente modificabile.

Passaggio 1: Creare l'interfaccia utente modificabile nell'elemento di DataList s ItemTemplate

Nell'esercitazione precedente, in cui viene creato un oggetto DataList a livello di elemento standard, sono stati usati due modelli:

  • ItemTemplate contiene l'interfaccia utente di sola lettura (controlli Web etichetta per la visualizzazione di ogni nome e prezzo del prodotto).
  • EditItemTemplate contiene l'interfaccia utente della modalità di modifica (i due controlli Web TextBox).

La proprietà DataList EditItemIndex determina il DataListItem rendering (se presente) tramite .EditItemTemplate In particolare, il DataListItem cui ItemIndex valore corrisponde alla proprietà di DataList viene EditItemIndex eseguito il rendering usando .EditItemTemplate Questo modello funziona bene quando è possibile modificare un solo elemento alla volta, ma si separa quando si crea un oggetto DataList completamente modificabile.

Per un DataList completamente modificabile, si vuole che tutti gliDataListItem elementi di rendering usino l'interfaccia modificabile. Il modo più semplice per eseguire questa operazione consiste nel definire l'interfaccia ItemTemplatemodificabile in . Per modificare le informazioni sull'indirizzo dei fornitori, l'interfaccia modificabile contiene il nome del fornitore come testo e quindi Caselle di testo per i valori indirizzo, città e paese/area geografica.

Iniziare aprendo la BatchUpdate.aspx pagina, aggiungere un controllo DataList e impostarne la ID proprietà su Suppliers. Dallo smart tag dataList scegliere di aggiungere un nuovo controllo ObjectDataSource denominato SuppliersDataSource.

Creare un nuovo oggettoDataSource denominato SuppliersDataSource

Figura 2: Creare un nuovo oggettoDataSource denominato SuppliersDataSource (fare clic per visualizzare l'immagine a dimensioni complete)

Configurare ObjectDataSource per recuperare i dati usando il SuppliersBLL metodo della GetSuppliers() classe (vedere la figura 3). Come per l'esercitazione precedente, anziché aggiornare le informazioni sul fornitore tramite ObjectDataSource, si funzionerà direttamente con il livello di logica di business. Impostare quindi l'elenco a discesa su (Nessuno) nella scheda UPDATE (vedere la figura 4).

Recuperare informazioni sul fornitore usando il metodo GetSuppliers()

Figura 3: Recuperare le informazioni sul fornitore usando il metodo (fare clic per visualizzare l'immagineGetSuppliers() full-size)

Impostare l'elenco di Drop-Down su (Nessuna) nella scheda UPDATE

Figura 4: Impostare l'elenco di Drop-Down su (Nessuno) nella scheda UPDATE (Fare clic per visualizzare l'immagine a dimensioni complete)

Al termine della procedura guidata, Visual Studio genera automaticamente DataList s ItemTemplate per visualizzare ogni campo dati restituito dall'origine dati in un controllo Web etichetta. È necessario modificare questo modello in modo che fornisca invece l'interfaccia di modifica. L'oggetto ItemTemplate può essere personalizzato tramite il Designer usando l'opzione Modifica modelli dallo smart tag di DataList o direttamente tramite la sintassi dichiarativa.

È necessario creare un'interfaccia di modifica che visualizza il nome del fornitore come testo, ma include Caselle di testo per l'indirizzo, la città e il paese/area del fornitore. Dopo aver apportato queste modifiche, la sintassi dichiarativa della pagina dovrebbe essere simile alla seguente:

<asp:DataList ID="Suppliers" runat="server" DataKeyField="SupplierID"
    DataSourceID="SuppliersDataSource">
    <ItemTemplate>
        <h4><asp:Label ID="CompanyNameLabel" runat="server"
            Text='<%# Eval("CompanyName") %>' /></h4>
        <table border="0">
            <tr>
                <td class="SupplierPropertyLabel">Address:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="Address" runat="server"
                        Text='<%# Eval("Address") %>' />
                </td>
            </tr>
            <tr>
                <td class="SupplierPropertyLabel">City:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="City" runat="server"
                        Text='<%# Eval("City") %>' />
                </td>
            </tr>
            <tr>
                <td class="SupplierPropertyLabel">Country:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="Country" runat="server"
                        Text='<%# Eval("Country") %>' />
                </td>
            </tr>
        </table>
        <br />
    </ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>

Nota

Come per l'esercitazione precedente, DataList in questa esercitazione deve avere lo stato di visualizzazione abilitato.

Nell'oggetto ItemTemplate sto usando due nuove classi CSS e SupplierPropertyValue, SupplierPropertyLabel che sono state aggiunte alla Styles.css classe e configurate per usare le stesse impostazioni di stile delle ProductPropertyLabel classi e ProductPropertyValue CSS.

.ProductPropertyLabel, .SupplierPropertyLabel
{
    font-weight: bold;
    text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
    padding-right: 35px;
}

Dopo aver apportato queste modifiche, visitare questa pagina tramite un browser. Come illustrato nella figura 5, ogni elemento DataList visualizza il nome del fornitore come testo e usa Caselle di testo per visualizzare l'indirizzo, la città e il paese/area geografica.

Ogni fornitore in DataList è modificabile

Figura 5: ogni fornitore nell'elenco dati è modificabile (fare clic per visualizzare l'immagine a dimensioni complete)

Passaggio 2: Aggiunta di un pulsante Aggiorna tutto

Mentre ogni fornitore nella figura 5 include i campi indirizzo, città e paese/area geografica visualizzati in una casella di testo, attualmente non è disponibile alcun pulsante Aggiorna. Anziché avere un pulsante Aggiorna per elemento, con DataList completamente modificabili è in genere presente un singolo pulsante Aggiorna tutto nella pagina che, quando si fa clic, aggiorna tutti i record nell'elenco dati. Per questa esercitazione, consente di aggiungere due pulsanti Update All : uno nella parte superiore della pagina e uno nella parte inferiore (anche se facendo clic su entrambi i pulsanti avrà lo stesso effetto).

Iniziare aggiungendo un controllo Web Button sopra DataList e impostandone la ID proprietà su UpdateAll1. Aggiungere quindi il secondo controllo Web Button sotto l'oggetto DataList, impostandone su IDUpdateAll2. Impostare le Text proprietà per i due pulsanti su Aggiorna tutto. Infine, creare gestori eventi per entrambi gli eventi Button Click . Anziché duplicare la logica di aggiornamento in ognuno dei gestori eventi, consentire di eseguire il refactoring della logica in un terzo metodo, UpdateAllSupplierAddresses, avendo i gestori eventi semplicemente richiamando questo terzo metodo.

Protected Sub UpdateAll1_Click(sender As Object, e As EventArgs) _
    Handles UpdateAll1.Click
    UpdateAllSupplierAddresses()
End Sub
Protected Sub UpdateAll2_Click(sender As Object, e As EventArgs) _
    Handles UpdateAll2.Click
    UpdateAllSupplierAddresses()
End Sub
Private Sub UpdateAllSupplierAddresses()
    ' TODO: Write code to update _all_ of the supplier addresses in the DataList
End Sub

La figura 6 mostra la pagina dopo l'aggiunta dei pulsanti Aggiorna tutti.

Sono stati aggiunti due pulsanti aggiorna tutti alla pagina

Figura 6: Sono stati aggiunti due pulsanti di aggiornamento alla pagina (fare clic per visualizzare l'immagine a dimensioni complete)

Passaggio 3: Aggiornamento di tutte le informazioni sugli indirizzi dei fornitori

Con tutti gli elementi di DataList che visualizzano l'interfaccia di modifica e con l'aggiunta dei pulsanti Aggiorna tutto, tutto ciò che rimane sta scrivendo il codice per eseguire l'aggiornamento batch. In particolare, è necessario eseguire il ciclo degli elementi di DataList e chiamare il SuppliersBLL metodo della UpdateSupplierAddress classe per ognuno di essi.

La raccolta di DataListItem istanze a cui è possibile accedere datalist tramite la proprietà DataList.Items Con un riferimento a , DataListItemè possibile acquisire il corrispondente SupplierID dalla DataKeys raccolta e fare riferimento a livello di codice ai controlli Web TextBox all'interno ItemTemplate del codice seguente:

Private Sub UpdateAllSupplierAddresses()
    ' Create an instance of the SuppliersBLL class
    Dim suppliersAPI As New SuppliersBLL()
    ' Iterate through the DataList's items
    For Each item As DataListItem In Suppliers.Items
        ' Get the supplierID from the DataKeys collection
        Dim supplierID As Integer = Convert.ToInt32(Suppliers.DataKeys(item.ItemIndex))
        ' Read in the user-entered values
        Dim address As TextBox = CType(item.FindControl("Address"), TextBox)
        Dim city As TextBox = CType(item.FindControl("City"), TextBox)
        Dim country As TextBox = CType(item.FindControl("Country"), TextBox)
        Dim addressValue As String = Nothing, _
            cityValue As String = Nothing, _
            countryValue As String = Nothing
        If address.Text.Trim().Length > 0 Then
            addressValue = address.Text.Trim()
        End If
        If city.Text.Trim().Length > 0 Then
            cityValue = city.Text.Trim()
        End If
        If country.Text.Trim().Length > 0 Then
            countryValue = country.Text.Trim()
        End If
        ' Call the SuppliersBLL class's UpdateSupplierAddress method
        suppliersAPI.UpdateSupplierAddress _
            (supplierID, addressValue, cityValue, countryValue)
    Next
End Sub

Quando l'utente fa clic su uno dei pulsanti Update All, il UpdateAllSupplierAddresses metodo esegue l'iterazione di ognuno DataListItem in Suppliers DataList e chiama il SuppliersBLL metodo della UpdateSupplierAddress classe, passando i valori corrispondenti. Un valore non immesso per indirizzo, città o paese/area geografica passa è un valore di Nothing a UpdateSupplierAddress (anziché una stringa vuota), che genera un database NULL per i campi dei record sottostanti.

Nota

Come miglioramento, è possibile aggiungere un controllo Web etichetta di stato alla pagina che fornisce un messaggio di conferma dopo l'esecuzione dell'aggiornamento batch.

Aggiornamento solo di questi indirizzi modificati

L'algoritmo di aggiornamento batch usato per questa esercitazione chiama il UpdateSupplierAddress metodo per ogni fornitore in DataList, indipendentemente dal fatto che le informazioni sull'indirizzo siano state modificate. Anche se tali aggiornamenti ciechi non sono in genere un problema di prestazioni, possono causare record superflui se si controllano le modifiche alla tabella di database. Ad esempio, se si usano trigger per registrare tutti gli elementi nella Suppliers tabella in una tabella di controllo, ogni volta che un utente fa clic sul pulsante Aggiorna tutto UPDATE verrà creato un nuovo record di controllo per ogni fornitore nel sistema, indipendentemente dal fatto che l'utente abbia apportato modifiche.

Le classi DataTable e DataAdapter ADO.NET sono progettate per supportare gli aggiornamenti batch in cui vengono generati solo record modificati, eliminati e nuovi record in qualsiasi comunicazione di database. Ogni riga in DataTable ha una RowState proprietà che indica se la riga è stata aggiunta alla Tabella dati, eliminata da essa, modificata o rimane invariata. Quando una tabella dati viene inizialmente popolata, tutte le righe vengono contrassegnate come invariate. La modifica del valore di una delle colonne della riga contrassegna la riga come modificato.

SuppliersBLL Nella classe vengono aggiornate le informazioni relative all'indirizzo del fornitore specificato leggendo prima il record del singolo fornitore in un SuppliersDataTable e quindi impostando i Addressvalori di colonna , CityCountry e usando il codice seguente:

Public Function UpdateSupplierAddress _
    (supplierID As Integer, address As String, city As String, country As String) _
    As Boolean
    Dim suppliers As Northwind.SuppliersDataTable = _
        Adapter.GetSupplierBySupplierID(supplierID)
    If suppliers.Count = 0 Then
        ' no matching record found, return false
        Return False
    Else
        Dim supplier As Northwind.SuppliersRow = suppliers(0)
        If address Is Nothing Then
            supplier.SetAddressNull()
        Else
            supplier.Address = address
        End If
        If city Is Nothing Then
            supplier.SetCityNull()
        Else
            supplier.City = city
        End If
        If country Is Nothing Then
            supplier.SetCountryNull()
        Else
            supplier.Country = country
        End If
        ' Update the supplier Address-related information
        Dim rowsAffected As Integer = Adapter.Update(supplier)
        ' Return true if precisely one row was updated, otherwise false
        Return rowsAffected = 1
    End If
End Function

Questo codice assegna in modo ingenuo i valori di indirizzo passato, città e paese/area geografica all'interno SuppliersRowSuppliersDataTable indipendentemente dal fatto che i valori siano stati modificati. Queste modifiche determinano che la SuppliersRow proprietà s RowState venga contrassegnata come modificata. Quando viene chiamato il metodo livello di accesso Update ai dati, viene visualizzato che è SupplierRow stato modificato e quindi invia un UPDATE comando al database.

Si supponga, tuttavia, che sia stato aggiunto codice a questo metodo per assegnare solo i valori di indirizzo, città e paese/area geografica passati se differiscono dai SuppliersRow valori esistenti. Nel caso in cui l'indirizzo, la città e l'area geografica siano uguali ai dati esistenti, non verranno apportate modifiche e l'oggetto SupplierRow verrà RowState contrassegnato come invariato. Il risultato netto è che quando viene chiamato il metodo S di Update DAL, non verrà eseguita alcuna chiamata al database perché non SuppliersRow è stata modificata.

Per applicare questa modifica, sostituire le istruzioni che assegnano in modo cieco gli indirizzi passati, la città e i valori paese/area geografica con il codice seguente:

' Only assign the values to the SupplierRow's column values if they differ
If address Is Nothing AndAlso Not supplier.IsAddressNull() Then
    supplier.SetAddressNull()
ElseIf (address IsNot Nothing AndAlso supplier.IsAddressNull) _
    OrElse (Not supplier.IsAddressNull() AndAlso _
                String.Compare(supplier.Address, address) <> 0) Then
    supplier.Address = address
End If
If city Is Nothing AndAlso Not supplier.IsCityNull() Then
    supplier.SetCityNull()
ElseIf (city IsNot Nothing AndAlso supplier.IsCityNull) _
    OrElse (Not supplier.IsCityNull() AndAlso _
                String.Compare(supplier.City, city) <> 0) Then
    supplier.City = city
End If
If country Is Nothing AndAlso Not supplier.IsCountryNull() Then
    supplier.SetCountryNull()
ElseIf (country IsNot Nothing AndAlso supplier.IsCountryNull) _
    OrElse (Not supplier.IsCountryNull() AndAlso _
                String.Compare(supplier.Country, country) <> 0) Then
    supplier.Country = country
End If

Con questo codice aggiunto, il metodo dal Update dal invia un'istruzione UPDATE al database solo per i record i cui valori correlati all'indirizzo sono stati modificati.

In alternativa, è possibile tenere traccia del fatto che siano presenti differenze tra i campi degli indirizzi passati e i dati del database e, se non sono presenti, è sufficiente ignorare la chiamata al metodo s dal Update . Questo approccio funziona correttamente se si usa il metodo diretto del database, poiché il metodo diretto del database non viene passato a un'istanza SuppliersRow di cui RowState è possibile verificare se è effettivamente necessaria una chiamata di database.

Nota

Ogni volta che viene richiamato il UpdateSupplierAddress metodo, viene effettuata una chiamata al database per recuperare informazioni sul record aggiornato. In caso di modifiche apportate ai dati, viene eseguita un'altra chiamata al database per aggiornare la riga della tabella. Questo flusso di lavoro può essere ottimizzato creando un overload di metodo che accetta un'istanza UpdateSupplierAddressEmployeesDataTable con tutte le modifiche apportate dalla BatchUpdate.aspx pagina. Quindi, potrebbe effettuare una chiamata al database per ottenere tutti i record dalla Suppliers tabella. I due set di risultati potrebbero quindi essere enumerati e solo i record in cui si sono verificati cambiamenti potrebbero essere aggiornati.

Riepilogo

In questa esercitazione è stato illustrato come creare un DataList completamente modificabile, consentendo a un utente di modificare rapidamente le informazioni sull'indirizzo per più fornitori. È stata avviata la definizione dell'interfaccia di modifica di un controllo Web TextBox per l'indirizzo, la città e il paese/area geografica del fornitore in DataList s ItemTemplate. Successivamente, sono stati aggiunti tutti i pulsanti sopra e sotto l'elenco dati. Dopo che un utente ha apportato le modifiche e ha fatto clic su uno dei pulsanti Update All, vengono DataListItem enumerati e viene eseguita una chiamata al SuppliersBLL metodo della UpdateSupplierAddress classe.

Buon programmatori!

Informazioni sull'autore

Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, lavora con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Può essere raggiunto all'indirizzo mitchell@4GuysFromRolla.com. o tramite il suo blog, disponibile all'indirizzo http://ScottOnWriting.NET.

Grazie speciale a

Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali di questa esercitazione sono stati Zack Jones e Ken Pespisa. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciami una riga in mitchell@4GuysFromRolla.com.