批次刪除 (VB)
演講者:Scott Mitchell
了解如何在單一操作中刪除多個資料庫記錄。 在使用者介面層中,我們將根據之前教學課程中建立的增強型 GridView 進行擴展。 在資料存取層中,我們將多個刪除操作包裝在一個交易中,以確保所有刪除成功或所有刪除都會回滾。
簡介
先前的教學課程探討如何使用完全可編輯的 GridView 建立批次編輯介面。 在使用者經常同時編輯多個記錄的情況下,批次編輯介面將需要的回傳和鍵盤到滑鼠上下文切換的次數更少,從而提高終端使用者的效率。 這種技術對於使用者經常一次性刪除多筆記錄的頁面同樣非常有用。
使用過線上電子郵件用戶端的任何人都已經熟悉最常見的批次刪除介面之一:網格中每行都有一個核取方塊,並帶有相應的「刪除所有選取的項目」按鈕 (見圖 1)。 這個教學課程相對較短,因為我們在之前的教學課程中已經完成了所有辛苦的工作,包括建立基於網頁的介面和實現一次性刪除多筆記錄的方法。 在「新增 GridView 核取方塊列」教學課程中,我們建立了一個包含核取方塊的 GridView 列。在「將資料庫修改包裝在交易中」教學課程中,我們在 BLL 中建立了一個方法,該方法將使用交易來刪除 ProductID
值的 List<T>
。 在本教學課程中,我們將整合之前的經驗,建立一個可工作的批次刪除範例。
圖 1:每行都將包含一個核取方塊 (點擊查看完整圖片)
步驟 1:建立批次刪除介面
由於我們在「新增 GridView 核取方塊列」教學課程中已經建立了批次刪除介面,因此我們只需將其複製到 BatchDelete.aspx
即可,而不必從頭開始建立。 首先,打開 BatchData
資料夾中的 BatchDelete.aspx
頁面和 EnhancedGridView
資料夾中的 CheckBoxField.aspx
頁面。 從 CheckBoxField.aspx
頁面移至「來源」檢視,並複製 <asp:Content>
標籤之間的標記,如圖 2 所示。
圖 2:將 CheckBoxField.aspx
的宣告式標記複製到剪貼簿 (點擊查看完整圖片)
接下來,前往 BatchDelete.aspx
中的來源檢視,並將剪貼簿的內容貼到 <asp:Content>
標籤內。 另外,將 CheckBoxField.aspx.vb
中的程式碼隱藏類別中的程式碼複製並貼上到 BatchDelete.aspx.vb
中的程式碼隱藏類別中 (DeleteSelectedProducts
按鈕的 Click
事件處理常式、ToggleCheckState
方法以及 CheckAll
和 UncheckAll
按鈕的Click
事件處理常式)。 複製此內容後,BatchDelete.aspx
頁面的程式碼隱藏類別應包含以下程式碼:
Partial Class BatchData_BatchDelete
Inherits System.Web.UI.Page
Protected Sub DeleteSelectedProducts_Click(sender As Object, e As EventArgs) _
Handles DeleteSelectedProducts.Click
Dim atLeastOneRowDeleted As Boolean = False
' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
' Access the CheckBox
Dim cb As CheckBox = row.FindControl("ProductSelector")
If cb IsNot Nothing AndAlso cb.Checked Then
' Delete row! (Well, not really...)
atLeastOneRowDeleted = True
' First, get the ProductID for the selected row
Dim productID As Integer = _
Convert.ToInt32(Products.DataKeys(row.RowIndex).Value)
' "Delete" the row
DeleteResults.Text &= String.Format _
("This would have deleted ProductID {0}<br />", productID)
'... To actually delete the product, use ...
' Dim productAPI As New ProductsBLL
' productAPI.DeleteProduct(productID)
'............................................
End If
Next
' Show the Label if at least one row was deleted...
DeleteResults.Visible = atLeastOneRowDeleted
End Sub
Private Sub ToggleCheckState(ByVal checkState As Boolean)
' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
' Access the CheckBox
Dim cb As CheckBox = row.FindControl("ProductSelector")
If cb IsNot Nothing Then
cb.Checked = checkState
End If
Next
End Sub
Protected Sub CheckAll_Click(sender As Object, e As EventArgs) _
Handles CheckAll.Click
ToggleCheckState(True)
End Sub
Protected Sub UncheckAll_Click(sender As Object, e As EventArgs) _
Handles UncheckAll.Click
ToggleCheckState(False)
End Sub
End Class
複製宣告性標記和原始程式碼後,花點時間透過瀏覽器查看來測試 BatchDelete.aspx
。 您應該會看到一個 GridView 列出了 GridView 中的前十個產品,每行都列出了產品的名稱、類別和價格以及一個核取方塊。 應有三個按鈕:全部選取、全部取消選取、刪除所選產品。 按一下「全部選取」按鈕將選取所有核取方塊,而「取消全部選取」將清除所有核取方塊。 點擊「刪除所選產品」會顯示一則訊息,其中列出了所選產品的 ProductID
值,但實際上並沒有刪除產品。
圖 3:CheckBoxField.aspx
的介面已移至 BatchDeleting.aspx
(點擊查看完整圖片)
步驟 2:使用交易刪除選取的產品
將批次刪除介面成功複製到 BatchDeleting.aspx
後,剩下的就是更新程式碼,以便「刪除所選產品」按鈕使用 ProductsBLL
類別中的 DeleteProductsWithTransaction
方法刪除選取的產品。 此方法會新增在「在交易中包裝資料庫修改」教學課程中,接受 ProductID
值的 List(Of T)
作為其輸入,並刪除交易範圍內的每個對應的 ProductID
。
DeleteSelectedProducts
按鈕的 Click
事件處理常式目前使用以下 For Each
循環來迭代每個 GridView 行:
' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
' Access the CheckBox
Dim cb As CheckBox = row.FindControl("ProductSelector")
If cb IsNot Nothing AndAlso cb.Checked Then
' Delete row! (Well, not really...)
atLeastOneRowDeleted = True
' First, get the ProductID for the selected row
Dim productID As Integer = _
Convert.ToInt32(Products.DataKeys(row.RowIndex).Value)
' "Delete" the row
DeleteResults.Text &= String.Format _
("This would have deleted ProductID {0}<br />", productID)
'... To actually delete the product, use ...
' Dim productAPI As New ProductsBLL
' productAPI.DeleteProduct(productID)
'............................................
End If
Next
對於每一行,都會以程式設計方式參考 ProductSelector
CheckBox Web 控制項。 如果選取該選項,則會從 DataKeys
集合中擷取行的 ProductID
,並更新 DeleteResults
標籤的 Text
屬性以包含一則訊息,指示已選取該行進行刪除。
上面的程式碼實際上並沒有刪除任何記錄,因為對 ProductsBLL
類別的 Delete
方法的呼叫已被註解掉。如果套用此刪除邏輯,程式碼將刪除產品,但不會在原子操作中刪除。 也就是說,如果序列中的前幾次刪除成功,但後來的幾次刪除失敗 (可能由於違反外部索引鍵限制),則會擲回例外狀況,但已刪除的那些產品將保持刪除狀態。
為了確保原子性,我們需要使用 ProductsBLL
類別的 DeleteProductsWithTransaction
方法。 因為此方法接受 ProductID
值清單,所以我們需要先從網格編譯此清單,然後將其作為參數傳遞。 我們會先建立 Integer
類型的 List(Of T)
執行個體。 在 For Each
循環中,我們需要將所選產品的 ProductID
值新增至此 List(Of T)
。 循環之後,此 List(Of T)
必須傳遞到 ProductsBLL
類別的 DeleteProductsWithTransaction
方法。 使用以下程式碼更新 DeleteSelectedProducts
按鈕的 Click
事件處理常式:
Protected Sub DeleteSelectedProducts_Click(sender As Object, e As EventArgs) _
Handles DeleteSelectedProducts.Click
' Create a List to hold the ProductID values to delete
Dim productIDsToDelete As New System.Collections.Generic.List(Of Integer)
' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
' Access the CheckBox
Dim cb As CheckBox = CType(row.FindControl("ProductSelector"), CheckBox)
If cb IsNot Nothing AndAlso cb.Checked Then
' Save the ProductID value for deletion
' First, get the ProductID for the selected row
Dim productID As Integer = _
Convert.ToInt32(Products.DataKeys(row.RowIndex).Value)
' Add it to the List...
productIDsToDelete.Add(productID)
' Add a confirmation message
DeleteResults.Text &= String.Format _
("ProductID {0} has been deleted<br />", productID)
End If
Next
' Call the DeleteProductsWithTransaction method and show the Label
' if at least one row was deleted...
If productIDsToDelete.Count > 0 Then
Dim productAPI As New ProductsBLL()
productAPI.DeleteProductsWithTransaction(productIDsToDelete)
DeleteResults.Visible = True
' Rebind the data to the GridView
Products.DataBind()
End If
End Sub
更新後的程式碼建立 Integer
(productIDsToDelete
) 類型的 List(Of T)
,並用要刪除的 ProductID
值填入。 For Each
循環結束後,如果至少選擇了一種產品,則呼叫 ProductsBLL
類別的 DeleteProductsWithTransaction
方法並傳遞此清單。 DeleteResults
標籤也會顯示,並且資料會重新繫結到 GridView (這樣新刪除的記錄就不會再作為行出現在網格中)。
圖 4 顯示了選擇刪除多行後的 GridView。 圖 5 顯示了點擊「刪除所選產品」按鈕後立即出現的畫面。 請注意,在圖 5 中,已刪除記錄的ProductID
值顯示在 GridView 下方的標籤中,而這些行不再出現在 GridView 中。
圖 4:將刪除所選產品 (點擊查看完整圖片)
圖 5:已刪除產品的 ProductID
值列在 GridView 下方 (點擊查看完整圖片)
注意
若要測試 DeleteProductsWithTransaction
方法的原子性,請手動在 Order Details
表格中新增產品項目,然後嘗試刪除該產品 (以及其他產品)。 嘗試刪除具有關聯訂單的產品時,您將收到外部索引鍵約束衝突,但請注意其他選定產品的刪除是如何回溯的。
摘要
建立批次刪除介面涉及新增一個帶有核取方塊列的 GridView 和一個 Button Web 控制項,當按一下該控制項時,將作為單一原子操作刪除所有選取的行。 在本教學課程中,我們透過將前兩個教學課程「新增 GridView 核取方塊列」和「將資料庫修改包裝在交易中」中完成的工作拼湊在一起來建立這樣的介面。 在第一個教學課程中,我們建立了一個帶有一列核取方塊的 GridView,在後者中,我們在BLL 中實作了一個方法,當傳遞 ProductID
值的 List(Of T)
時,會在交易範圍內將它們全部刪除。
在下一個教學課程中,我們將建立一個用於執行批次插入的介面。
快樂程式!
關於作者
Scott Mitchell 是七本 ASP/ASP.NET 書籍的作者,也是 4GuysFromRolla.com 的創辦人,自 1998 年以來一直在使用 Microsoft 網路技術。 Scott 是一位獨立顧問、培訓師兼作家。 他的最新著作是 Sams Teach Yourself ASP.NET 2.0 in 24 Hours。 您可以透過電子郵件聯繫他:mitchell@4GuysFromRolla.com。 或者透過他的部落格與他聯繫,網址為 http://ScottOnWriting.NET。
特別感謝
本教學課程系列已經過許多熱心的審閱者檢閱。 本教學課程的主要審閱者是 Hilton Giesenow 和 Teresa Murphy。 有興趣查看我即將發表的 MSDN 文章嗎? 如果是的話,請傳送郵件給我:mitchell@4GuysFromRolla.com。