Aggiornamento batch (VB)
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 eseguite il wrapping di più operazioni di aggiornamento all'interno di una transazione per assicurarsi che tutti gli aggiornamenti abbiano esito positivo o che venga eseguito il rollback di tutti gli aggiornamenti.
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 verrà considerata come un'unica operazione atomica, che garantisce che tutte le modifiche avranno esito negativo o tutte avranno esito positivo. Grazie a questa funzionalità DAL di basso livello, è possibile concentrarsi sulla creazione di interfacce di modifica dei dati batch.
In questa esercitazione verrà creato un controllo GridView in cui ogni riga è modificabile (vedere la figura 1). Poiché viene eseguito il rendering di ogni riga nell'interfaccia di modifica, non è necessaria una colonna di pulsanti Modifica, Aggiornamento e Annulla. Nella pagina sono invece presenti due pulsanti Aggiorna prodotti che, quando si fa clic, enumerano le righe gridView e aggiornano il database.
Figura 1: Ogni riga in GridView è modificabile (fare clic per visualizzare l'immagine a dimensione intera)
Iniziamo!
Nota
Nell'esercitazione Esecuzione di aggiornamenti batch è stata creata un'interfaccia di modifica batch usando il controllo DataList. Questa esercitazione è diversa da quella precedente in che usa 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à relativa alle transazioni di database aggiunta nell'esercitazione precedente.
Esame dei passaggi per rendere modificabili tutte le righe gridView
Come illustrato nell'esercitazione Panoramica sull'inserimento , l'aggiornamento e l'eliminazione di dati , GridView offre il supporto predefinito per la modifica dei dati sottostanti in base a righe. Internamente, GridView annota la riga modificabile tramite la relativa EditIndex
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, il rendering dei campi della riga viene eseguito usando le relative interfacce di modifica. Per BoundFields, l'interfaccia di modifica è un controllo TextBox la cui Text
proprietà è assegnata al valore del campo dati specificato dalla proprietà BoundField s DataField
. Per TemplateFields, EditItemTemplate
viene usato al posto di ItemTemplate
.
Tenere presente che il flusso di lavoro di modifica inizia quando un utente fa clic sul pulsante Modifica di una riga. In questo modo viene generato un postback, viene impostata la proprietà gridView sull'indice EditIndex
della riga selezionata e i dati vengono riassociati alla griglia. Quando si fa clic sul pulsante Annulla di una riga, al postback EditIndex
viene impostato su un valore di -1
prima di riassociare i dati alla griglia. Poiché le righe di GridView iniziano l'indicizzazione a zero, l'impostazione EditIndex
su -1
ha 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 controllo GridView, è necessario che ogni riga esegua il rendering usando l'interfaccia di modifica. Il modo più semplice per eseguire questa operazione consiste nel creare dove ogni campo modificabile viene implementato come TemplateField con la relativa interfaccia di modifica definita in ItemTemplate
.
Nei diversi passaggi successivi verrà creato un controllo GridView completamente modificabile. Nel passaggio 1 si inizierà creando GridView e il relativo ObjectDataSource e convertirne BoundFields e CheckBoxField in TemplateFields. Nei passaggi 2 e 3 le interfacce di modifica verranno spostate da TemplateFields EditItemTemplate
alle rispettive ItemTemplate
interfacce.
Passaggio 1: Visualizzazione delle informazioni sul prodotto
Prima di preoccuparsi della creazione di un controllo GridView in cui sono modificabili le righe, è possibile iniziare visualizzando semplicemente le informazioni sul prodotto. Aprire la BatchUpdate.aspx
pagina nella BatchData
cartella e trascinare gridView dalla casella degli strumenti nella finestra di progettazione. Impostare GridView s ID
su ProductsGrid
e, dallo smart tag, scegliere di associarlo a un nuovo ObjectDataSource denominato ProductsDataSource
. Configurare ObjectDataSource per recuperare i dati dal ProductsBLL
metodo della GetProducts
classe .
Figura 2: Configurare ObjectDataSource per l'uso della classe (fare clic per visualizzare l'immagine ProductsBLL
a dimensione intera)
Figura 3: Recuperare i dati del prodotto usando il metodo (fare clic per visualizzare l'immagine GetProducts
a dimensione intera)
Analogamente a GridView, le funzionalità di modifica di ObjectDataSource sono progettate per funzionare in base alle righe. Per aggiornare un set di record, è necessario scrivere un po' di codice nella classe code-behind della pagina ASP.NET che esegue il batch dei dati e lo passa al BLL. Pertanto, impostare gli elenchi a discesa nelle schede UPDATE, INSERT e DELETE di ObjectDataSource su (Nessuno). Fare clic su Fine per completare la procedura guidata.
Figura 4: Impostare gli elenchi a discesa nelle schede UPDATE, INSERT e DELETE su (Nessuno) (Fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver completato la procedura guidata Configura origine dati, il markup dichiarativo di ObjectDataSource dovrebbe 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 fa sì che Visual Studio crei BoundFields e checkBoxField per i campi dati del prodotto in GridView. Per questa esercitazione, consentire all'utente di visualizzare e modificare solo il nome, la categoria, il prezzo e lo stato sospeso del prodotto. Rimuovere tutti i ProductName
campi , CategoryName
, UnitPrice
, e e Discontinued
rinominare le HeaderText
proprietà dei primi tre campi rispettivamente in Product, Category e Price. Infine, selezionare le caselle di controllo Abilita paging e Abilita ordinamento nello smart tag gridView.
A questo punto GridView ha tre BoundFields (ProductName
, CategoryName
e UnitPrice
) e un CheckBoxField (Discontinued
). È necessario convertire questi quattro campi in TemplateFields e quindi spostare l'interfaccia di modifica da TemplateField a EditItemTemplate
.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 rispettivi ItemTemplate
s, ma se ci si blocca o è necessario un aggiornamento, non esitare a fare riferimento a questa esercitazione precedente.
Dallo smart tag 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 modello.
Figura 5: Convertire i campi boundfield esistenti e CheckBoxField in campi modello
Ora che ogni campo è un campo TemplateField, è possibile spostare l'interfaccia di modifica da EditItemTemplate
s a ItemTemplate
s.
Passaggio 2: CreazioneProductName
UnitPrice
di interfacce eDiscontinued
modifica
La creazione delle ProductName
interfacce , UnitPrice
e di Discontinued
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ù complessa 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 dallo smart tag gridView e eseguire il ProductName
drill-down in TemplateField s EditItemTemplate
. Selezionare il controllo TextBox, copiarlo negli Appunti e incollarlo nell'oggetto ProductName
TemplateField s ItemTemplate
. Modificare la proprietà TextBox s ID
in ProductName
.
Aggiungere quindi un RequiredFieldValidator a 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 a , la ItemTemplate
schermata dovrebbe essere simile alla figura 6.
Figura 6: TemplateField ProductName
include ora una casella di testo e un oggetto RequiredFieldValidator (fare clic per visualizzare l'immagine a dimensione intera)
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 compareValidator a 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., la relativa Text
proprietà su *, la relativa Type
proprietà su Currency
, la Operator
relativa proprietà su GreaterThanEqual
e la relativa ValueToCompare
proprietà su 0 .
Figura 7: Aggiungere un compareValidator per assicurarsi che il prezzo immesso sia un valore di valuta non negativo (fare clic per visualizzare l'immagine a dimensione intera)
Discontinued
Per TemplateField è possibile usare il controllo CheckBox già definito in ItemTemplate
. È sufficiente impostarne su ID
Discontinued e la relativa Enabled
proprietà su True
.
Passaggio 3: Creazione dell'interfacciaCategoryName
di modifica
L'interfaccia CategoryName
di modifica in TemplateField EditItemTemplate
contiene un controllo TextBox che visualizza il valore del CategoryName
campo dati. È necessario sostituirlo con un elenco a discesa che elenca le possibili categorie.
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é un controllo TextBox. 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 dropDownList dalla casella degli strumenti in CategoryName
TemplateField s ItemTemplate
, impostandone su Categories
ID
. A questo punto si definirà in genere l'origine dati dropDownLists tramite lo smart tag, creando un nuovo ObjectDataSource. Tuttavia, questo aggiungerà 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 finestra di progettazione sotto ProductsDataSource
ObjectDataSource. Denominare il nuovo ObjectDataSource CategoriesDataSource
e configurarlo per l'uso del CategoriesBLL
metodo della classe .GetCategories
Figura 8: Configurare ObjectDataSource per l'uso della classe (fare clic per visualizzare l'immagine CategoriesBLL
a dimensione intera)
Figura 9: Recuperare i dati delle categorie usando il metodo (fare clic per visualizzare l'immagine GetCategories
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.
Figura 10: Impostare gli elenchi a discesa nelle schede UPDATE e DELETE su (Nessuno) (Fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver completato la procedura guidata, il CategoriesDataSource
markup dichiarativo deve 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 s, 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.
Figura 11: Associare l'elenco a discesa a (fare clic per visualizzare l'immagineCategoriesDataSource
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 dropDownList Categories
s SelectedValue
sul valore del CategoryID
prodotto. Fare clic sul collegamento Edit DataBindings (Modifica DataBindings) dallo smart tag DropDownList s e associare la SelectedValue
proprietà al CategoryID
campo dati, come illustrato nella figura 12.
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. Ciò è dovuto al fatto che l'elenco a discesa 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 s AppendDataBoundItems
su True
e aggiungere un nuovo elemento a DropDownList, omettendo la Value
proprietà dalla sintassi dichiarativa. Ovvero, 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 - Selezionare uno - ha il <asp:ListItem Value="">
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 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 molto breve basata sul tempo.
Passaggio 4: Completamento dell'interfaccia di modifica
Sono state apportate numerose modifiche ai modelli di GridView senza sospendere la visualizzazione dello stato di avanzamento. Per visualizzare lo stato di avanzamento, passare da 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.
Figura 13: Ogni riga gridView è modificabile (fare clic per visualizzare l'immagine a dimensione intera)
Ci sono alcuni problemi di formattazione minori che dovremmo occuparsi a questo punto. Prima di tutto, si noti che il UnitPrice
valore contiene quattro punti decimali. Per risolvere il problema, tornare a UnitPrice
TemplateField s ItemTemplate
e, dallo smart tag textBox, fare clic sul collegamento Modifica dataBindings. Specificare quindi che la Text
proprietà deve essere formattata come numero.
Figura 14: Formattare la Text
proprietà come numero
In secondo luogo, 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 Discontinued
TemplateField nell'elenco dei campi nell'angolo inferiore sinistro. Eseguire il drill-down ItemStyle
e impostare la HorizontalAlign
proprietà su Center come illustrato nella figura 15.
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 Update Products .
Poiché l'interfaccia di modifica di GridView è definita nei relativi campi Template, 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 dovrebbe essere simile alla 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>
La figura 16 mostra questa pagina quando viene visualizzata tramite un browser dopo l'aggiunta dei controlli Web Button e le modifiche di formattazione apportate.
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
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
chiamata al metodo BLL.GetProducts
Enumera quindi la ProductGrid
raccolta di Rows
GridView. La Rows
raccolta contiene un'istanza GridViewRow
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 viene ProductID
afferrata dall'insieme DataKeys
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 che ogni valore della riga gridView è stato usato per aggiornare , ProductsDataTable
viene passato al metodo BLL cheUpdateWithTransaction
, come illustrato nell'esercitazione precedente, semplicemente chiama verso il basso nel metodo dal.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 sul prodotto siano state modificate. Sebbene tali aggiornamenti non vedenti non siano in genere un problema di prestazioni, possono causare record superflui se si controllano le modifiche alla tabella di database. Tornare all'esercitazione Esecuzione di aggiornamenti batch è stata esaminata un'interfaccia di aggiornamento batch con DataList e il codice aggiunto 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 della chiave primaria dell'origine dati alla proprietà GridView.DataKeyNames
Se l'oggetto 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 di 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 richiamare il BatchUpdate
metodo 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 di tutto 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, prendere in considerazione l'aggiunta di un vincolo casuale CHECK
, ad esempio uno che non consente i UnitPrice
valori 1234.56. Quindi da BatchUpdate.aspx
modificare un numero di record, assicurandosi di impostare un valore del UnitPrice
prodotto sul valore non consentito ( 1234,56 ). Questo dovrebbe generare 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 questo caso, ottenere tutti i prodotti dal database solo per modificare 10 di essi è minore dell'ideale.
Per questi tipi di situazioni, prendere in considerazione l'uso del 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 vuoto ProductsDataTable
denominato products
. Viene quindi eseguita la procedura per la raccolta di Rows
GridView e per ogni riga vengono recuperate le informazioni specifiche sul prodotto usando il metodo BLL.GetProductByProductID(productID)
L'istanza recuperata ProductsRow
ha le relative proprietà aggiornate nello stesso modo di BatchUpdate
, ma dopo l'aggiornamento della riga viene importata in ProductsDataTable
products
tramite il metodo DataTable sImportRow(DataRow)
.
Al termine del ciclo, products
contiene un'istanza ProductsRow
For Each
per ogni riga in GridView. Poiché ognuna delle ProductsRow
istanze è stata aggiunta a products
(anziché aggiornata), se viene passata 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).
A tale scopo, è possibile aggiungere un nuovo metodo al BLL denominato UpdateProductsWithTransaction
. UpdateProductsWithTransaction
, illustrato di seguito, imposta l'oggetto RowState
di ognuna delle ProductsRow
istanze di in Modified
ProductsDataTable
e quindi passa l'oggetto ProductsDataTable
al metodo dalUpdateWithTransaction
.
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 non supporta la creazione di interfacce completamente modificabili. Come illustrato in questa esercitazione, queste interfacce sono possibili, ma richiedono un po ' di lavoro. Per creare un controllo GridView in cui ogni riga è modificabile, è necessario convertire i campi di GridView in TemplateFields e definire l'interfaccia di modifica all'interno di ItemTemplate
s. Inoltre, è necessario aggiungere alla pagina tutti i controlli Web Pulsante di tipo Aggiornamento, separati da GridView. Questi gestori eventi Buttons Click
devono enumerare la raccolta di Rows
GridView, archiviare le modifiche in un ProductsDataTable
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 gridView includerà una casella di controllo e invece dei pulsanti Aggiorna tutto -tipo, saranno disponibili i pulsanti Elimina righe selezionate.
Buon programmatori!
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato 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, che può essere trovato all'indirizzo http://ScottOnWriting.NET.
Grazie speciale a
Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali per questa esercitazione erano Teresa Murphy e David Suru. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciarmi una riga in mitchell@4GuysFromRolla.com.