執行批次更新 (VB)
瞭解如何建立完全可編輯的 DataList,其中其所有專案都處於編輯模式,且其值可以透過按兩下頁面上的 [全部更新] 按鈕來儲存。
簡介
在 上述教學課程 中,我們檢查了如何建立專案層級的 DataList。 就像標準可編輯的 GridView 一樣,DataList 中的每個專案都包含 [編輯] 按鈕,按兩下時,專案可以編輯。 雖然此專案層級編輯適用於偶爾只會更新的數據,但某些使用案例需要使用者編輯許多記錄。 如果使用者需要編輯數十筆記錄,並強制按兩下 [編輯],進行其變更,然後按兩下每一筆記錄的 [更新],按兩下次數可能會降低其生產力。 在這種情況下,更好的選項是提供完全可編輯的 DataList,其中 其所有 專案都處於編輯模式,而且按下頁面上的 [全部更新] 按鈕即可編輯其值, (請參閱圖 1) 。
圖 1:可完整編輯 DataList 中的每個專案都可以修改 (按兩下即可檢視完整大小的影像)
在本教學課程中,我們將探討如何讓使用者使用完全可編輯的 DataList 來更新供應商地址資訊。
步驟 1:在 DataList s ItemTemplate 中建立可編輯的使用者介面
在上述教學課程中,我們會在其中建立標準、專案層級可編輯的 DataList,我們使用兩個範本:
ItemTemplate
包含唯讀使用者介面, (標籤 Web 控件,以顯示每個產品名稱和價格) 。EditItemTemplate
包含編輯模式使用者介面, (兩個 TextBox Web 控件) 。
DataList s EditItemIndex
屬性會指定 DataListItem
如果使用 轉譯任何) , EditItemTemplate
(。 特別是, DataListItem
其 ItemIndex
值符合 DataList s EditItemIndex
屬性的 會使用 EditItemTemplate
轉譯。 當一次只能編輯一個專案,但建立可完全編輯的 DataList 時,此模型可正常運作。
針對完全可編輯的 DataList,我們想要使用可編輯的介面來轉譯 所有DataListItem
。 完成此作業的最簡單方式是在 中定義可編輯的 ItemTemplate
介面。 若要修改供應商地址資訊,可編輯的介面包含供應商名稱做為文字,然後是位址、城市和國家/地區值的 TextBoxes。
從開啟頁面開始 BatchUpdate.aspx
,新增 DataList 控制項,並將其屬性設定 ID
為 Suppliers
。 從 DataList 的智慧標記中,選擇新增名為 SuppliersDataSource
的新 ObjectDataSource 控件。
圖 2:建立名為 SuppliersDataSource
的新 ObjectDataSource (按兩下即可檢視大小完整的映射)
設定 ObjectDataSource 以使用 SuppliersBLL
類別 s GetSuppliers()
方法擷取數據 (請參閱圖 3) 。 如同上述教學課程,我們不會透過 ObjectDataSource 更新供應商資訊,而是直接使用商業規則層。 因此,將下拉式清單設定為 [更新] 索引標籤中的 ([無) ], (請參閱圖 4) 。
圖 3:使用 GetSuppliers()
方法擷取供貨商資訊 (按兩下以檢視全尺寸影像)
圖 4:將 [Drop-Down 列表] 設定 (為 [更新] 索引卷標的 [無) ] (按兩下即可檢視完整大小的映像)
完成精靈之後,Visual Studio 會自動產生 DataList s ItemTemplate
以顯示卷標 Web 控件中數據源所傳回的每個數據欄位。 我們需要修改此範本,使其改為提供編輯介面。 ItemTemplate
可以使用 DataList 智慧標記中的 [編輯範本] 選項,或直接透過宣告式語法,透過 Designer 自定義 。
請花點時間建立編輯介面,將供貨商的名稱顯示為文字,但包含供應商位址、城市和國家/地區值的 TextBox。 進行這些變更之後,頁面的宣告式語法看起來應該如下所示:
<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>
注意
如同上述教學課程,本教學課程中的 DataList 必須啟用其檢視狀態。
在ItemTemplate
我使用的是兩個新的 CSS 類別和 SupplierPropertyValue
,SupplierPropertyLabel
這些類別已新增至 Styles.css
類別,並設定為使用與 和 ProductPropertyValue
CSS 類別相同的樣式設定ProductPropertyLabel
。
.ProductPropertyLabel, .SupplierPropertyLabel
{
font-weight: bold;
text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
padding-right: 35px;
}
進行這些變更之後,請透過瀏覽器瀏覽此頁面。 如圖 5 所示,每個 DataList 項目都會以文字顯示供應商名稱,並使用 TextBox 來顯示位址、城市和國家/地區。
圖 5:D ataList 中的每個供應商都是可編輯的 (按兩下即可檢視完整大小的影像)
步驟 2:新增 [全部更新] 按鈕
雖然圖 5 中的每個供應商都有其位址、城市和國家/地區字段顯示在 TextBox 中,但目前沒有可用的 [更新] 按鈕。 相較於每個專案的 [更新] 按鈕,具有完全可編輯的 DataLists,頁面上通常會有單一的 [全部更新] 按鈕,按兩下時,會更新 DataList 中的所有 記錄。 在本教學課程中,讓我們新增兩個 [全部更新] 按鈕 - 一個位於頁面頂端,另一個位於底部 (,雖然按兩下任一按鈕會有相同的效果) 。
首先,在 DataList 上方新增 Button Web 控制件,並將其 屬性設定 ID
為 UpdateAll1
。 接下來,在 DataList 底下新增第二個 Button Web 控件,並將其 ID
設定為 UpdateAll2
。 將 Text
兩個按鈕的屬性設定為 [全部更新]。 最後,建立這兩個 Buttons Click
事件的事件處理程式。 讓我們將邏輯重構為第三個方法,而不要複製每個事件處理程式中的更新邏輯,而是將該邏輯重構為第三個方法, UpdateAllSupplierAddresses
讓事件處理程式只叫用這個第三個方法。
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
圖 6 顯示新增 [全部更新] 按鈕之後的頁面。
圖 6:已將兩個更新所有按鈕新增至頁面 (按兩下以檢視大小完整的映像)
步驟 3:更新所有供應商地址資訊
當所有 DataList 項目顯示編輯介面,以及新增 [全部更新] 按鈕時,保留的所有項目都會撰寫程式代碼以執行批次更新。 具體而言,我們需要迴圈處理 DataList 的專案,併為每個專案呼叫 SuppliersBLL
類別 s UpdateSupplierAddress
方法。
可以透過 DataList 的 屬性存取 DataList 的Items
實例集合DataListItem
。 使用 的DataListItem
參考,我們可以從DataKeys
集合擷取對應的 SupplierID
,並以程式設計方式參考 中的 ItemTemplate
TextBox Web 控制項,如下列程式碼所示:
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
當使用者按兩下其中一個 [全部更新] 按鈕時, UpdateAllSupplierAddresses
方法會逐一查看 DataListItem
DataList中的每個 Suppliers
按鈕,並呼叫 SuppliersBLL
類別 s UpdateSupplierAddress
方法,並傳入對應的值。 位址、城市或國家/地區傳遞的非輸入值是 (UpdateSupplierAddress
的值Nothing
,而不是空白字串) ,這會導致基礎記錄字段的資料庫NULL
。
注意
為了增強功能,您可能會想要將狀態標籤 Web 控件新增至頁面,以在執行批次更新之後提供一些確認訊息。
僅更新已修改的位址
本教學課程所使用的批次更新演算法會針對 DataList 中的每個供應商呼叫UpdateSupplierAddress
方法,不論其地址資訊是否已變更。 雖然這類盲目更新通常不是效能問題,但如果您重新稽核資料庫數據表的變更,可能會導致多餘的記錄。 例如,如果您使用觸發程式將所有記錄 UPDATE
到稽核數據表, Suppliers
每當使用者按兩下 [全部更新] 按鈕時,系統中的每個供應商都會建立新的稽核記錄,不論使用者是否進行任何變更。
ADO.NET DataTable 和 DataAdapter 類別的設計目的是支援批次更新,其中只有修改、刪除和新記錄會導致任何資料庫通訊。 DataTable 中的每個數據列都有屬性RowState
,指出數據列是否已新增至 DataTable、從其中刪除、修改或保持不變。 一開始填入 DataTable 時,所有數據列都會標示為未變更。 變更任何數據列數據列的值,會將數據列標示為已修改。
在類別中, SuppliersBLL
我們會先在單一供應商記錄中讀取至 SuppliersDataTable
,然後使用下列程式代碼來設定 Address
、 City
和數據 Country
行值,以更新指定的供應商地址資訊:
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
不論值是否已變更,此程式代碼都會將傳入的位址、城市和國家/地區值指派給 SuppliersRow
中的 SuppliersDataTable
。 這些修改會導致 SuppliersRow
s RowState
屬性標示為已修改。 呼叫數據存取層的 Update
方法時,會看到 SupplierRow
已修改 ,因此會將命令傳送 UPDATE
至資料庫。
不過,想像一下,我們已將程式代碼新增至這個方法,以便只有在傳入的位址、城市和國家/地區值與 SuppliersRow
現有值不同時,才指派傳入的位址、城市和國家/地區值。 在位址、城市和國家/地區與現有資料相同的情況下,不會進行任何變更,且 SupplierRow
RowState
會保留標示為未變更的 。 最終結果是呼叫 DAL s Update
方法時,不會進行任何資料庫呼叫,因為 SuppliersRow
尚未修改 。
若要制定這項變更,請使用下列程式代碼取代不小心指派傳入位址、城市和國家/地區值的語句:
' 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
使用這個新增的程式代碼,DAL s Update
方法只會針對地址相關值已變更的記錄,將語句傳送 UPDATE
至資料庫。
或者,我們可以追蹤傳遞的位址字段與資料庫數據之間是否有任何差異,如果沒有任何,只要略過對 DAL s Update
方法的呼叫即可。 如果您使用 DB 直接方法,此方法會正常運作,因為 DB 直接方法並未傳遞 SuppliersRow
可檢查的實例 RowState
,以判斷是否實際需要資料庫呼叫。
注意
每次 UpdateSupplierAddress
叫用 方法時,都會呼叫資料庫以擷取更新記錄的相關信息。 然後,如果數據有任何變更,則會對資料庫進行另一次呼叫來更新數據表數據列。 建立方法多載,以接受EmployeesDataTable
具有頁面所有變更的BatchUpdate.aspx
實例,藉此優化UpdateSupplierAddress
此工作流程。 然後,它可以對資料庫進行一次呼叫,以從 Suppliers
數據表取得所有記錄。 然後可以列舉這兩個結果集,而且只能更新發生變更的記錄。
摘要
在本教學課程中,我們已瞭解如何建立完全可編輯的 DataList,讓使用者快速修改多個供應商的地址資訊。 我們從定義 DataList s ItemTemplate
中供應商位址、城市和國家/地區值的 TextBox Web 控制項編輯介面開始。 接下來,我們新增了 DataList 上方和下方的 [更新所有] 按鈕。 當使用者進行變更並按兩下其中一個 [全部更新] 按鈕之後,會 DataListItem
列舉 s,並 SuppliersBLL
呼叫 類別 s UpdateSupplierAddress
方法。
快樂的程序設計!
關於作者
Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 自 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET。
特別感謝
本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的首席檢閱者是 Zack Jones 和 Ken Pespisa。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應