Aggiornamento batch (VB)

di Scott Mitchell

Scarica il PDF

Informazioni su come aggiornare più record di database in una singola operazione. Nel livello interfaccia utente viene creato un controllo GridView in cui ogni riga è modificabile. Nel livello di accesso ai dati vengono eseguito il wrapping di più operazioni di aggiornamento all'interno di una transazione per garantire che tutti gli aggiornamenti abbiano esito positivo o tutti gli aggiornamenti vengano eseguito il rollback.

Introduzione

Nell'esercitazione precedente è stato illustrato come estendere il livello di accesso ai dati per aggiungere il supporto per le transazioni di database. Le transazioni di database garantiscono che una serie di istruzioni di modifica dei dati venga considerata come un'operazione atomica, che garantisce che tutte le modifiche avranno esito negativo o tutte avranno esito positivo. Grazie a questa funzionalità DAL di basso livello, siamo pronti a richiamare l'attenzione sulla creazione di interfacce di modifica dei dati batch.

In questa esercitazione si creerà Un controllo GridView in cui ogni riga è modificabile (vedere la figura 1). Poiché ogni riga viene eseguito il rendering nell'interfaccia di modifica, non è necessaria alcuna colonna di pulsanti Modifica, Aggiornamento e Annulla. Esistono invece due pulsanti Aggiorna prodotti nella pagina che, quando si fa clic, enumera le righe GridView e aggiorna il database.

Ogni riga in GridView è modificabile

Figura 1: Ogni riga in GridView è modificabile (fare clic per visualizzare l'immagine a dimensioni complete)

Iniziamo!

Nota

Nell'esercitazione Esecuzione di Batch Aggiornamenti è stata creata un'interfaccia di modifica batch usando il controllo DataList. Questa esercitazione differisce da quella precedente in cui viene usata una funzione GridView e l'aggiornamento batch viene eseguito nell'ambito di una transazione. Dopo aver completato questa esercitazione, è consigliabile tornare all'esercitazione precedente e aggiornarla per usare la funzionalità correlata alla transazione del database aggiunta nell'esercitazione precedente.

Esame dei passaggi per la modifica di tutte le righe di GridView

Come illustrato nell'esercitazione Panoramica dell'inserimento, dell'aggiornamento e dell'eliminazione dei dati , GridView offre il supporto predefinito per la modifica dei dati sottostanti in base a una riga. Internamente, GridView annota la riga modificabile tramite la relativaEditIndex proprietà. Poiché GridView è associato all'origine dati, controlla ogni riga per verificare se l'indice della riga è uguale al valore di EditIndex. In tal caso, i campi della riga vengono sottoposti a rendering usando le interfacce di modifica. Per BoundFields, l'interfaccia di modifica è una Casella di testo la cui Text proprietà viene assegnata al valore del campo dati specificato dalla proprietà BoundField.DataField Per TemplateFields, l'oggetto EditItemTemplateItemTemplateviene usato al posto di .

Si ricordi che il flusso di lavoro di modifica inizia quando un utente fa clic sul pulsante Modifica riga. In questo modo viene generato un postback, imposta la proprietà GridView sull'indice EditIndex della riga selezionata e ribina i dati nella griglia. Quando viene fatto clic sul pulsante Annulla riga, nel postback viene EditIndex impostato su un valore di -1 prima di ribindare i dati nella griglia. Poiché le righe di GridView iniziano l'indicizzazione a zero, l'impostazione EditIndex ha -1 l'effetto di visualizzare GridView in modalità di sola lettura.

La EditIndex proprietà funziona bene per la modifica per riga, ma non è progettata per la modifica in batch. Per rendere modificabile l'intero gridView, è necessario avere ogni rendering di riga usando l'interfaccia di modifica. Il modo più semplice per eseguire questa operazione consiste nel creare la posizione in cui ogni campo modificabile viene implementato come ModelloField con la relativa interfaccia di modifica definita in ItemTemplate.

Nei diversi passaggi successivi si creerà un gridView completamente modificabile. Nel passaggio 1 si inizierà creando GridView e il relativo OggettoDataSource e convertirne BoundFields e CheckBoxField in TemplateFields. Nei passaggi 2 e 3 verranno spostate le interfacce di modifica da TemplateFields EditItemTemplate alle relative ItemTemplate .

Passaggio 1: Visualizzazione delle informazioni sul prodotto

Prima di preoccuparsi della creazione di Un controllo GridView in cui le righe sono modificabili, è possibile iniziare visualizzando semplicemente le informazioni sul prodotto. Aprire la BatchUpdate.aspx pagina nella BatchData cartella e trascinare gridView dalla casella degli strumenti nella Designer. Impostare GridView su IDProductsGrid e, dal relativo smart tag, scegliere di associarlo a un nuovo OggettoDataSource denominato ProductsDataSource. Configurare ObjectDataSource per recuperare i dati dal ProductsBLL metodo della GetProducts classe.

Configurare ObjectDataSource per usare la classe ProductsBLL

Figura 2: Configurare ObjectDataSource per usare la classe (fare clic per visualizzare l'immagineProductsBLL full-size)

Recuperare i dati del prodotto usando il metodo GetProducts

Figura 3: Recuperare i dati del prodotto usando il metodo (fare clic per visualizzare l'immagineGetProducts full-size)

Analogamente a GridView, le funzionalità di modifica di ObjectDataSource sono progettate per funzionare su base per riga. Per aggiornare un set di record, è necessario scrivere un bit di codice nella classe code-behind della pagina ASP.NET che esegue il batch dei dati e lo passa al BLL. Impostare quindi gli elenchi a discesa nelle schede UPDATE, INSERT e DELETE di ObjectDataSource su (Nessuno). Fare clic su Fine per completare la procedura guidata.

Impostare la Drop-Down Elenchi nelle schede UPDATE, INSERT e DELETE su (Nessuno)

Figura 4: Impostare la Drop-Down Elenchi nelle schede UPDATE, INSERT e DELETE su (Nessuna) (Fare clic per visualizzare l'immagine a dimensioni complete)

Dopo aver completato la configurazione guidata origine dati, il markup dichiarativo di ObjectDataSource deve essere simile al seguente:

<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>

Il completamento della procedura guidata Configura origine dati determina anche che Visual Studio crei BoundFields e checkBoxField per i campi dati del prodotto in GridView. Per questa esercitazione, consenti solo all'utente di visualizzare e modificare il nome, la categoria, la categoria, il prezzo e lo stato interrotto. Rimuovere tutti i ProductNamecampi , CategoryName, UnitPricee Discontinued e rinominare rispettivamente le HeaderText proprietà dei primi tre campi in Product, Category e Price. Infine, selezionare le caselle di controllo Abilita paging e Abilita ordinamento nello smart tag di GridView.

A questo punto GridView ha tre BoundFields (ProductName, , e UnitPrice) e checkBoxField (DiscontinuedCategoryName). È necessario convertire questi quattro campi in TemplateFields e quindi spostare l'interfaccia di modifica da TemplateField EditItemTemplate al relativo ItemTemplate.

Nota

È stata esaminata la creazione e la personalizzazione di TemplateFields nell'esercitazione Personalizzazione dell'interfaccia di modifica dei dati . Verranno illustrati i passaggi per convertire BoundFields e CheckBoxField in TemplateFields e definire le relative interfacce di modifica nei ItemTemplate rispettivi s, ma se si è bloccati o si ha bisogno di un aggiornamento, non esitare a fare riferimento a questa esercitazione precedente.

Nella smart tag di GridView fare clic sul collegamento Modifica colonne per aprire la finestra di dialogo Campi. Selezionare quindi ogni campo e fare clic sul collegamento Converti questo campo in un campo TemplateField.

Convertire i Campi delimiti esistenti e CheckBoxField in templateFields

Figura 5: Convertire i campi Delimiti esistenti e CheckBoxField in templateFields

Ora che ogni campo è un ModelloField, è possibile spostare l'interfaccia EditItemTemplate di modifica da s a ItemTemplate s.

Passaggio 2: Creazione diProductNameUnitPrice interfacce eDiscontinuedmodifica

La creazione di ProductNameinterfacce , UnitPricee Discontinued di modifica sono l'argomento di questo passaggio e sono piuttosto semplici, poiché ogni interfaccia è già definita in TemplateField s EditItemTemplate. La creazione dell'interfaccia CategoryName di modifica è un po' più coinvolta perché è necessario creare un elenco a discesa delle categorie applicabili. Questa CategoryName interfaccia di modifica viene affrontata nel passaggio 3.

Iniziamo con ProductName TemplateField. Fare clic sul collegamento Modifica modelli dal smart tag di GridView e eseguire il drill-down su ProductName TemplateField s EditItemTemplate. Selezionare TextBox, copiarlo negli Appunti e quindi incollarlo nell'oggetto ProductName TemplateField s ItemTemplate. Modificare la proprietà TextBox s ID in ProductName.

Aggiungere quindi un oggetto RequiredFieldValidator all'oggetto ItemTemplate per assicurarsi che l'utente fornisca un valore per ogni nome del prodotto. Impostare la ControlToValidate proprietà su ProductName, la ErrorMessage proprietà su È necessario specificare il nome del prodotto. e la Text proprietà su *. Dopo aver effettuato queste aggiunte alla schermata , lo schermo dovrebbe essere simile alla ItemTemplatefigura 6.

Il modello ProductName TemplateField include ora una casella di testo e un oggetto RequiredFieldValidator

Figura 6: TemplateField ProductName include ora una casella di testo e un oggetto RequiredFieldValidator (fare clic per visualizzare un'immagine full-size)

Per l'interfaccia UnitPrice di modifica, iniziare copiando TextBox dall'oggetto EditItemTemplate a ItemTemplate. Posizionare quindi un $ davanti a TextBox e impostarne la ID proprietà su UnitPrice e la relativa Columns proprietà su 8 .

Aggiungere anche un CompareValidator all'oggetto UnitPrice s ItemTemplate per assicurarsi che il valore immesso dall'utente sia un valore di valuta valido maggiore o uguale a $0,00. Impostare la proprietà del ControlToValidate validator su UnitPrice, la relativa ErrorMessage proprietà su È necessario immettere un valore di valuta valido. Omettere qualsiasi simbolo di valuta., Text la relativa proprietà su *, la relativa proprietà su Currency, la OperatorType relativa proprietà su e la relativa ValueToCompare proprietà su GreaterThanEqual0 .

Aggiungere un compareValidator per assicurarsi che il prezzo immesso sia un valore di valuta non negativo

Figura 7: Aggiungere un compareValidator per assicurarsi che il prezzo immesso sia un valore valuta non negativo (fare clic per visualizzare l'immagine a dimensioni complete)

Discontinued Per TemplateField è possibile usare checkBox già definito in ItemTemplate. È sufficiente impostarne ID su Discontinued e la relativa Enabled proprietà su True.

Passaggio 3: Creazione dell'interfacciaCategoryNamedi modifica

L'interfaccia CategoryName di modifica in TemplateField contiene EditItemTemplate una casella di testo che visualizza il valore del CategoryName campo dati. È necessario sostituire questa operazione con un elenco a discesa che elenca le categorie possibili.

Nota

L'esercitazione Personalizzazione dell'interfaccia di modifica dei dati contiene una discussione più approfondita e completa sulla personalizzazione di un modello per includere un elenco a discesa anziché una casella di testo. Mentre i passaggi qui sono completati, vengono presentati in modo tersely. Per un'analisi più approfondita della creazione e della configurazione delle categorie DropDownList, vedere l'esercitazione Personalizzazione dell'interfaccia di modifica dei dati .

Trascinare un oggetto DropDownList dalla casella degli strumenti nel CategoryName campo TemplateField, ItemTemplateimpostandone il ID valore su Categories. A questo punto si definirà in genere l'origine dati dropDownLists tramite lo smart tag, creando un nuovo ObjectDataSource. Tuttavia, verrà aggiunto ObjectDataSource all'interno di ItemTemplate, che comporterà la creazione di un'istanza ObjectDataSource per ogni riga gridView. Creare invece ObjectDataSource all'esterno di TemplateFields di GridView. Terminare la modifica del modello e trascinare ObjectDataSource dalla casella degli strumenti nella Designer sotto ProductsDataSource ObjectDataSource. Denominare il nuovo ObjectDataSource CategoriesDataSource e configurarlo per l'uso del CategoriesBLL metodo della GetCategories classe .

Configurare ObjectDataSource per l'uso della classe CategoriesBLL

Figura 8: Configurare ObjectDataSource per l'uso della classe (fare clic per visualizzare l'immagineCategoriesBLL a dimensione intera)

Recuperare i dati delle categorie usando il metodo GetCategories

Figura 9: Recuperare i dati delle categorie usando il GetCategories metodo (fare clic per visualizzare l'immagine a dimensione intera)

Poiché ObjectDataSource viene usato solo per recuperare i dati, impostare gli elenchi a discesa nelle schede UPDATE e DELETE su (Nessuno). Fare clic su Fine per completare la procedura guidata.

Impostare il Drop-Down Elenchi nelle schede UPDATE e DELETE su (Nessuno)

Figura 10: Impostare il Drop-Down Elenchi nelle schede UPDATE e DELETE su (Nessuno) (Fare clic per visualizzare l'immagine a dimensione intera)

Al termine della procedura guidata, il CategoriesDataSource markup dichiarativo dovrebbe essere simile al seguente:

<asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

Dopo la creazione e la CategoriesDataSource configurazione, tornare a CategoryName TemplateField s ItemTemplate e, dallo smart tag dropDownList, fare clic sul collegamento Scegli origine dati. Nella configurazione guidata origine dati selezionare l'opzione CategoriesDataSource nel primo elenco a discesa e scegliere di usare CategoryName per la visualizzazione e CategoryID come valore.

Associare DropDownList a CategoriesDataSource

Figura 11: Associare l'elenco a discesa a CategoriesDataSource (fare clic per visualizzare l'immagine a dimensione intera)

A questo punto l'elenco Categories a discesa elenca tutte le categorie, ma non seleziona ancora automaticamente la categoria appropriata per il prodotto associato alla riga GridView. A tale scopo, è necessario impostare Categories DropDownList s SelectedValue sul valore del CategoryID prodotto. Fare clic sul collegamento Modifica DataBindings dallo smart tag DropDownList e associare la SelectedValue proprietà al CategoryID campo dati, come illustrato nella figura 12.

Associare il valore CategoryID del prodotto alla proprietà SelectedValue di DropDownList

Figura 12: Associare il valore del CategoryID prodotto alla proprietà dropDownList s SelectedValue

Un ultimo problema rimane: se il prodotto non ha un CategoryID valore specificato, l'istruzione databinding su SelectedValue genererà un'eccezione. Questo avviene perché DropDownList contiene solo gli elementi per le categorie e non offre un'opzione per i prodotti che hanno un NULL valore di database per CategoryID. Per risolvere questo problema, impostare la proprietà DropDownList su AppendDataBoundItems e aggiungere un nuovo elemento a DropDownList, omettendo la Value proprietà dalla sintassi dichiarativa.True In altri casi, assicurarsi che la Categories sintassi dichiarativa di DropDownList sia simile alla seguente:

<asp:DropDownList ID="Categories" runat="server" AppendDataBoundItems="True" 
    DataSourceID="CategoriesDataSource" DataTextField="CategoryName" 
    DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'>
    <asp:ListItem Value=">-- Select One --</asp:ListItem>
</asp:DropDownList>

Si noti che - <asp:ListItem Value=""> Selezionare uno - ha il relativo Value attributo impostato in modo esplicito su una stringa vuota. Fare riferimento all'esercitazione Personalizzazione dell'interfaccia di modifica dei dati per una discussione più approfondita sul motivo per cui questo elemento DropDownList aggiuntivo è necessario per gestire il NULL caso e perché l'assegnazione Value della proprietà a una stringa vuota è essenziale.

Nota

Qui è presente un potenziale problema di prestazioni e scalabilità che vale la pena menzionare. Poiché ogni riga ha un oggetto DropDownList che usa CategoriesDataSource come origine dati, il CategoriesBLL metodo della GetCategories classe verrà chiamato n volte per visita di pagina, dove n è il numero di righe in GridView. Queste n chiamate per GetCategories generare n query al database. Questo impatto sul database può essere ridotto memorizzando nella cache le categorie restituite in una cache per richiesta o tramite il livello di memorizzazione nella cache tramite una dipendenza di memorizzazione nella cache SQL o una scadenza basata su tempo molto breve.

Passaggio 4: Completamento dell'interfaccia di modifica

Sono state apportate alcune modifiche ai modelli di GridView senza sospendere per visualizzare lo stato di avanzamento. Dedicare qualche minuto a visualizzare lo stato di avanzamento tramite un browser. Come illustrato nella figura 13, viene eseguito il rendering di ogni riga usando il relativo ItemTemplate, che contiene l'interfaccia di modifica della cella.

Ogni riga gridView è modificabile

Figura 13: Ogni riga gridView è modificabile (fare clic per visualizzare l'immagine a dimensione intera)

Ci sono alcuni problemi di formattazione secondari che dovremmo occuparsi a questo punto. Si noti innanzitutto che il UnitPrice valore contiene quattro punti decimali. Per risolvere questo problema, tornare a UnitPrice TemplateField s ItemTemplate e, dallo smart tag di TextBox, fare clic sul collegamento Modifica DataBindings. Specificare quindi che la Text proprietà deve essere formattata come numero.

Formattare la proprietà Text come numero

Figura 14: Formattare la Text proprietà come numero

In secondo luogo, è possibile allineare al centro la casella di controllo nella Discontinued colonna anziché allinearla a sinistra. Fare clic su Modifica colonne dallo smart tag gridView e selezionare TemplateField Discontinued nell'elenco dei campi nell'angolo in basso a sinistra. Eseguire il drill-down ItemStyle e impostare la HorizontalAlign proprietà su Center come illustrato nella figura 15.

Centrare il checkBox sospeso

Figura 15: Centrare il Discontinued controllo CheckBox

Aggiungere quindi un controllo ValidationSummary alla pagina e impostarne la ShowMessageBox proprietà su True e la relativa ShowSummary proprietà su False. Aggiungere anche i controlli Web Button che, quando si fa clic, aggiorneranno le modifiche dell'utente. In particolare, aggiungere due controlli Web Button, uno sopra GridView e uno sotto di esso, impostando entrambe le proprietà dei controlli Text su Aggiorna prodotti .

Poiché l'interfaccia di modifica di GridView è definita nei relativi campi TemplateFields, gli EditItemTemplate oggetti sono superflui ItemTemplate e possono essere eliminati.

Dopo aver apportato le modifiche di formattazione indicate in precedenza, aggiungendo i controlli Button e rimuovendo gli elementi non necessari EditItemTemplate , la sintassi dichiarativa della pagina avrà un aspetto simile al seguente:

<p>
    <asp:Button ID="UpdateAllProducts1" runat="server" Text="Update Products" />
</p>
<p>
    <asp:GridView ID="ProductsGrid" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
        AllowPaging="True" AllowSorting="True">
        <Columns>
            <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
                <ItemTemplate>
                    <asp:TextBox ID="ProductName" runat="server" 
                        Text='<%# Bind("ProductName") %>'></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
                        ControlToValidate="ProductName"
                        ErrorMessage="You must provide the product's name." 
                        runat="server">*</asp:RequiredFieldValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Category" 
                SortExpression="CategoryName">
                <ItemTemplate>
                    <asp:DropDownList ID="Categories" runat="server" 
                        AppendDataBoundItems="True" 
                        DataSourceID="CategoriesDataSource"
                        DataTextField="CategoryName" 
                        DataValueField="CategoryID" 
                        SelectedValue='<%# Bind("CategoryID") %>'>
                        <asp:ListItem>-- Select One --</asp:ListItem>
                    </asp:DropDownList>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Price" 
                SortExpression="UnitPrice">
                <ItemTemplate>
                    $<asp:TextBox ID="UnitPrice" runat="server" Columns="8" 
                        Text='<%# Bind("UnitPrice", "{0:N}") %>'></asp:TextBox>
                    <asp:CompareValidator ID="CompareValidator1" runat="server" 
                        ControlToValidate="UnitPrice"
                        ErrorMessage="You must enter a valid currency value. 
                                      Please omit any currency symbols."
                        Operator="GreaterThanEqual" Type="Currency" 
                        ValueToCompare="0">*</asp:CompareValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
                <ItemTemplate>
                    <asp:CheckBox ID="Discontinued" runat="server" 
                        Checked='<%# Bind("Discontinued") %>' />
                </ItemTemplate>
                <ItemStyle HorizontalAlign="Center" />
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</p>
<p>
    <asp:Button ID="UpdateAllProducts2" runat="server" Text="Update Products" />
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetProducts" TypeName="ProductsBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetCategories" TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" 
        ShowMessageBox="True" ShowSummary="False" />
</p>

Nella figura 16 questa pagina viene visualizzata tramite un browser dopo l'aggiunta dei controlli Web Button e le modifiche di formattazione apportate.

La pagina include ora due pulsanti Aggiorna prodotti

Figura 16: La pagina include ora due pulsanti Aggiorna prodotti (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 5: Aggiornamento dei prodotti

Quando un utente visita questa pagina, apporta le modifiche e quindi fa clic su uno dei due pulsanti Aggiorna prodotti. A questo punto è necessario salvare in qualche modo i valori immessi dall'utente per ogni riga in un'istanza ProductsDataTable di e quindi passarlo a un metodo BLL che passerà quindi tale ProductsDataTable istanza al metodo dal UpdateWithTransaction . Il UpdateWithTransaction metodo creato nell'esercitazione precedente garantisce che il batch di modifiche venga aggiornato come operazione atomica.

Creare un metodo denominato BatchUpdate in BatchUpdate.aspx.vb e aggiungere il codice seguente:

Private Sub BatchUpdate()
    ' Enumerate the GridView's Rows collection and create a ProductRow
    Dim productsAPI As New ProductsBLL()
    Dim products As Northwind.ProductsDataTable = productsAPI.GetProducts()
    For Each gvRow As GridViewRow In ProductsGrid.Rows
        ' Find the ProductsRow instance in products that maps to gvRow
        Dim productID As Integer = _
            Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
        Dim product As Northwind.ProductsRow = products.FindByProductID(productID)
        If product IsNot Nothing Then
            ' Programmatically access the form field elements in the 
            ' current GridViewRow
            Dim productName As TextBox = _
                CType(gvRow.FindControl("ProductName"), TextBox)
            Dim categories As DropDownList = _
                CType(gvRow.FindControl("Categories"), DropDownList)
            Dim unitPrice As TextBox = _
                CType(gvRow.FindControl("UnitPrice"), TextBox)
            Dim discontinued As CheckBox = _
                CType(gvRow.FindControl("Discontinued"), CheckBox)
            ' Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim()
            If categories.SelectedIndex = 0 Then 
                product.SetCategoryIDNull() 
            Else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue)
            End If
            If unitPrice.Text.Trim().Length = 0 Then 
                product.SetUnitPriceNull() 
            Else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
            End If
            product.Discontinued = discontinued.Checked
        End If
    Next
    ' Now have the BLL update the products data using a transaction
    productsAPI.UpdateWithTransaction(products)
End Sub

Questo metodo inizia recuperando tutti i prodotti in una ProductsDataTable tramite una chiamata al metodo BLL.GetProducts Enumera quindi la ProductGrid raccolta di RowsGridView. La Rows raccolta contiene un'istanzaGridViewRow per ogni riga visualizzata in GridView. Poiché vengono visualizzate al massimo dieci righe per pagina, la raccolta di Rows GridView non avrà più di dieci elementi.

Per ogni riga, l'oggetto ProductIDDataKeys viene afferrato dalla raccolta e l'oggetto appropriato ProductsRow viene selezionato da ProductsDataTable. Ai quattro controlli di input TemplateField viene fatto riferimento a livello di codice e ai relativi valori assegnati alle proprietà dell'istanza ProductsRow . Dopo aver usato ogni valore della riga di GridView per aggiornare ProductsDataTable, viene passato al metodo BLL che UpdateWithTransaction , come illustrato nell'esercitazione precedente, chiama semplicemente nel metodo DAL s UpdateWithTransaction .

L'algoritmo di aggiornamento batch usato per questa esercitazione aggiorna ogni riga di ProductsDataTable che corrisponde a una riga in GridView, indipendentemente dal fatto che le informazioni del prodotto 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. Tornare all'esercitazione Esecuzione di batch Aggiornamenti è stata esaminata un'interfaccia di aggiornamento batch con DataList e è stato aggiunto codice che aggiornerebbe solo i record effettivamente modificati dall'utente. È possibile usare le tecniche di Esecuzione di Aggiornamenti Batch per aggiornare il codice in questa esercitazione, se necessario.

Nota

Quando si associa l'origine dati a GridView tramite lo smart tag, Visual Studio assegna automaticamente i valori di chiave primaria dell'origine dati alla proprietà gridView.DataKeyNames Se objectDataSource non è stato associato a GridView tramite lo smart tag di GridView come descritto nel passaggio 1, sarà necessario impostare manualmente la proprietà gridView su DataKeyNames ProductID per accedere al ProductID valore per ogni riga tramite l'insieme DataKeys .

Il codice usato in BatchUpdate è simile a quello usato nei metodi BLL, UpdateProduct la differenza principale è che nei UpdateProduct metodi viene recuperata solo una singola ProductRow istanza dall'architettura. Il codice che assegna le proprietà di ProductRow è lo stesso tra i UpdateProducts metodi e il codice all'interno del For Each ciclo in BatchUpdate, come è il modello complessivo.

Per completare questa esercitazione, è necessario che il BatchUpdate metodo venga richiamato quando si fa clic su uno dei pulsanti Aggiorna prodotti. Creare gestori eventi per gli Click eventi di questi due controlli Button e aggiungere il codice seguente nei gestori eventi:

BatchUpdate()
ClientScript.RegisterStartupScript(Me.GetType(), "message", _
    "alert('The products have been updated.');", True)

Prima viene effettuata una chiamata a BatchUpdate. Successivamente, la ClientScript proprietà viene usata per inserire JavaScript che visualizzerà una finestra di messaggio che legge I prodotti sono stati aggiornati.

Eseguire un minuto per testare questo codice. Visitare BatchUpdate.aspx un browser, modificare una serie di righe e fare clic su uno dei pulsanti Aggiorna prodotti. Supponendo che non siano presenti errori di convalida dell'input, verrà visualizzata una finestra di messaggio che legge I prodotti sono stati aggiornati. Per verificare l'atomicità dell'aggiornamento, è consigliabile aggiungere un vincolo casuale CHECK , ad esempio un vincolo che non consente UnitPrice valori di 1234.56. Quindi da BatchUpdate.aspxmodificare un numero di record, assicurandosi di impostare uno dei valori del UnitPrice prodotto sul valore non consentito ( 1234,56 ). Questo dovrebbe causare un errore quando si fa clic su Aggiorna prodotti con le altre modifiche durante l'operazione batch di cui è stato eseguito il rollback ai valori originali.

Metodo alternativoBatchUpdate

Il BatchUpdate metodo appena esaminato recupera tutti i prodotti dal metodo BLL e GetProducts quindi aggiorna solo i record visualizzati in GridView. Questo approccio è ideale se GridView non usa il paging, ma se lo fa, potrebbero esserci centinaia, migliaia o decine di migliaia di prodotti, ma solo dieci righe in GridView. In tal caso, ottenere tutti i prodotti dal database solo per modificare 10 di essi è minore dell'ideale.

Per questi tipi di situazioni, è consigliabile usare invece il metodo seguente BatchUpdateAlternate :

Private Sub BatchUpdateAlternate()
    ' Enumerate the GridView's Rows collection and create a ProductRow
    Dim productsAPI As New ProductsBLL()
    Dim products As New Northwind.ProductsDataTable()
    For Each gvRow As GridViewRow In ProductsGrid.Rows
        ' Create a new ProductRow instance
        Dim productID As Integer = _
            Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
        Dim currentProductDataTable As Northwind.ProductsDataTable = _
            productsAPI.GetProductByProductID(productID)
        If currentProductDataTable.Rows.Count > 0 Then
            Dim product As Northwind.ProductsRow = currentProductDataTable(0)
            Dim productName As TextBox = _
                CType(gvRow.FindControl("ProductName"), TextBox)
            Dim categories As DropDownList = _
                CType(gvRow.FindControl("Categories"), DropDownList)
            Dim unitPrice As TextBox = _
                CType(gvRow.FindControl("UnitPrice"), TextBox)
            Dim discontinued As CheckBox = _
                CType(gvRow.FindControl("Discontinued"), CheckBox)
            ' Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim()
            If categories.SelectedIndex = 0 Then 
                product.SetCategoryIDNull() 
            Else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue)
            End If
            If unitPrice.Text.Trim().Length = 0 Then 
                product.SetUnitPriceNull() 
            Else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
            End If
            product.Discontinued = discontinued.Checked
            ' Import the ProductRow into the products DataTable
            products.ImportRow(product)
        End If
    Next
    ' Now have the BLL update the products data using a transaction
    productsAPI.UpdateProductsWithTransaction(products)
End Sub

BatchMethodAlternate inizia creando un nuovo oggetto vuoto ProductsDataTable denominato products. Esegue quindi i passaggi della raccolta di Rows GridView e per ogni riga ottiene le informazioni specifiche sul prodotto usando il metodo BLL.GetProductByProductID(productID) L'istanza recuperata ProductsRow ha le proprietà aggiornate nello stesso modo di BatchUpdate, ma dopo l'aggiornamento della riga importata nel productsProductsDataTable metodo DataTable.ImportRow(DataRow)

Al termine del ciclo, products contiene un'istanza ProductsRowFor Each per ogni riga in GridView. Poiché ognuna delle ProductsRow istanze è stata aggiunta all'oggetto products (anziché aggiornata), se il metodo viene passato in modo cieco al UpdateWithTransaction metodo, ProductsTableAdapter tenterà di inserire ognuno dei record nel database. È invece necessario specificare che ognuna di queste righe è stata modificata (non aggiunta).

Questa operazione può essere eseguita aggiungendo un nuovo metodo al BLL denominato UpdateProductsWithTransaction. UpdateProductsWithTransaction, illustrato di seguito, imposta l'oggetto RowState di ognuna delle ProductsRow istanze nell'oggetto ProductsDataTable e Modified quindi passa il ProductsDataTable valore al metodo S di UpdateWithTransaction DAL.

Public Function UpdateProductsWithTransaction _
    (ByVal products As Northwind.ProductsDataTable) As Integer
    ' Mark each product as Modified
    products.AcceptChanges()
    For Each product As Northwind.ProductsRow In products
        product.SetModified()
    Next
    ' Update the data via a transaction
    Return UpdateWithTransaction(products)
End Function

Riepilogo

GridView offre funzionalità di modifica predefinite per riga, ma manca il supporto per la creazione di interfacce completamente modificabili. Come abbiamo visto in questa esercitazione, tali interfacce sono possibili, ma richiedono un po 'di lavoro. Per creare un oggetto GridView in cui ogni riga è modificabile, è necessario convertire i campi GridView in TemplateFields e definire l'interfaccia di modifica all'interno di ItemTemplate s. È inoltre necessario aggiungere tutti i controlli Web button -type alla pagina, separati da GridView. Questi gestori di eventi Button Click devono enumerare l'insieme GridView, Rows archiviare le modifiche in un ProductsDataTableoggetto e passare le informazioni aggiornate nel metodo BLL appropriato.

Nell'esercitazione successiva verrà illustrato come creare un'interfaccia per l'eliminazione batch. In particolare, ogni riga di GridView includerà una casella di controllo e invece dei pulsanti Aggiorna tutti i tipi, saranno disponibili pulsanti Elimina righe selezionate.

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 erano Teresa Murphy e David Suru. Interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami una riga in mitchell@4GuysFromRolla.com.