批次刪除 (C#)

作者:Scott Mitchell

下載 PDF

瞭解如何在單一作業中刪除多個資料庫記錄。 在使用者介面層中,我們會建立在稍早教學課程中建立的增強 GridView。 在資料存取層中,我們會在交易中包裝多個刪除作業,以確保所有刪除成功或所有刪除都會回復。

簡介

上述教學課程探索如何使用完全編輯的 GridView 建立批次編輯介面。 在用戶經常一次編輯許多記錄的情況下,批次編輯介面需要較少的回傳和鍵盤對滑鼠內容切換,進而改善使用者的效率。 這項技術同樣適用於使用者一次性刪除許多記錄的常見頁面。

已使用線上電子郵件用戶端的任何人都已經熟悉其中一個最常見的批次刪除介面:方格中每個數據列中都有對應的 [刪除所有核取專案] 按鈕的複選框, (請參閱圖 1) 。 本教學課程相當簡短,因為我們已在先前的教學課程中完成所有硬式工作,以建立網頁型介面和方法,將一系列記錄刪除為單一不可部分完成的作業。 在新增複選框的 GridView 資料行教學課程中,我們建立了具有複選框數據行的 GridView,以及在交易內包裝資料庫修改教學課程中,我們會在 BLL 中建立方法,以使用交易來刪除List<T>ProductID值的 。 在本教學課程中,我們將以先前的體驗為基礎並合併,以建立工作批次刪除範例。

每個數據列都包含複選框

圖 1:每個數據列都包含複選框 (按單擊即可檢視完整大小的影像)

步驟 1:建立批次刪除介面

由於我們已在 新增複選框的 GridView 資料 行教學課程中建立批次刪除介面,因此我們可以直接將其複製到 BatchDelete.aspx ,而不是從頭開始建立介面。 首先, BatchDelete.aspx 開啟資料夾中的頁面 BatchDataCheckBoxField.aspx 資料夾中的頁面 EnhancedGridViewCheckBoxField.aspx從頁面移至 [來源] 檢視,並在標記之間複製標記,<asp:Content>如圖 2 所示。

將 CheckBoxField.aspx的宣告式標記複製到剪貼簿

圖 2:將 的宣告式標記 CheckBoxField.aspx 複製到剪貼簿 (按兩下以檢視大小完整的影像)

接下來,移至 中的 BatchDelete.aspx [來源] 檢視,並在標記中 <asp:Content> 貼上剪貼簿的內容。 此外,將程式代碼後置類別CheckBoxField.aspx.cs中的 程式代碼複製並貼到 DeleteSelectedProductsBatchDelete.aspx.cs (Button Click 事件處理程式、ToggleCheckState方法,以及 ClickUncheckAll Buttons 的事件處理程式 CheckAll) 。 複製此內容之後, BatchDelete.aspx 頁面的程式代碼後置類別應該包含下列程式代碼:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class BatchData_BatchDelete : System.Web.UI.Page
{
    protected void DeleteSelectedProducts_Click(object sender, EventArgs e)
    {
        bool atLeastOneRowDeleted = false;
        // Iterate through the Products.Rows property
        foreach (GridViewRow row in Products.Rows)
        {
            // Access the CheckBox
            CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
            if (cb != null && cb.Checked)
            {
                // Delete row! (Well, not really...)
                atLeastOneRowDeleted = true;
                // First, get the ProductID for the selected row
                int productID = 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 ...
                //ProductsBLL productAPI = new ProductsBLL();
                //productAPI.DeleteProduct(productID);
                //............................................
            }
        }
        // Show the Label if at least one row was deleted...
        DeleteResults.Visible = atLeastOneRowDeleted;
    }
    private void ToggleCheckState(bool checkState)
    {
        // Iterate through the Products.Rows property
        foreach (GridViewRow row in Products.Rows)
        {
            // Access the CheckBox
            CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
            if (cb != null)
                cb.Checked = checkState;
        }
    }
    protected void CheckAll_Click(object sender, EventArgs e)
    {
        ToggleCheckState(true);
    }
    protected void UncheckAll_Click(object sender, EventArgs e)
    {
        ToggleCheckState(false);
    }
}

透過宣告式標記和原始碼複製之後,請透過瀏覽器檢視它來進行測試 BatchDelete.aspx 。 您應該會看到 GridView 列出 GridView 中的前十個產品,每個數據列都會列出產品名稱、類別和價格,以及一個複選框。 應該有三個按鈕:核取 [全部]、[取消核取全部] 和 [刪除選取的產品]。 按兩下 [全部核取] 按鈕會選取所有複選框,而 [全部取消核取] 會清除所有複選框。 按兩下 [刪除選取的產品] 會顯示一則訊息,其中列出 ProductID 所選產品的值,但實際上不會刪除產品。

CheckBoxField.aspx的介面已移至 BatchDeleting.aspx

圖 3:已將 的 CheckBoxField.aspx 介面移至 BatchDeleting.aspx (按兩下即可檢視完整大小的影像)

步驟 2:使用交易刪除已核取的產品

在批次刪除介面成功複製到 BatchDeleting.aspx之後,所有仍會更新程序代碼,讓 [刪除選取的產品] 按鈕會使用 DeleteProductsWithTransaction 類別中的 ProductsBLL 方法刪除已核取的產品。 這個方法會在交易教學課程的 Wrapping Database Modifications 中新增,接受作為值的輸入,List<T>ProductID並刪除交易範圍內每個對應的ProductID值。

DeleteSelectedProducts Button s Click 事件處理程式目前使用下列foreach迴圈逐一查看每個 GridView 數據列:

// Iterate through the Products.Rows property
foreach (GridViewRow row in Products.Rows)
{
    // Access the CheckBox
    CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
    if (cb != null && cb.Checked)
    {
        // Delete row! (Well, not really...)
        atLeastOneRowDeleted = true;
        // First, get the ProductID for the selected row
        int productID = 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 ...
        //ProductsBLL productAPI = new ProductsBLL();
        //productAPI.DeleteProduct(productID);
        //............................................
    }
}

針對每個數據列, ProductSelector 會以程序設計方式參考 CheckBox Web 控制件。 如果已核取數據列,則會從DataKeys集合擷取數據列ProductID,並DeleteResults更新 Label s Text 屬性以包含訊息,指出已選取要刪除的數據列。

上述程式代碼實際上不會刪除任何記錄,因為類別 s Delete 方法的ProductsBLL呼叫已批注化。這是要套用的刪除邏輯,程式代碼會刪除產品,但不在不可部分完成的作業內。 也就是說,如果序列中的前幾個刪除成功,但稍後的刪除失敗 (可能是因為外鍵條件約束違規) ,就會擲回例外狀況,但那些已經刪除的產品仍會遭到刪除。

為了保證不可部分完成性,我們必須改用 ProductsBLL 類別 s DeleteProductsWithTransaction 方法。 因為這個方法接受值清單,所以我們必須先從方格編譯此清單 ProductID ,然後將它當做參數傳遞。 我們先建立 型int別 的 List<T> 實例。 在迴圈中 foreach ,我們需要將選取的產品 ProductID 值新增至這個 List<T>。 迴圈之後,必須將這個 List<T> 傳遞至 ProductsBLL 類別 s DeleteProductsWithTransaction 方法。 DeleteSelectedProducts使用下列程式代碼更新 Button s Click 事件處理程式:

protected void DeleteSelectedProducts_Click(object sender, EventArgs e)
{
    // Create a List to hold the ProductID values to delete
    System.Collections.Generic.List<int> productIDsToDelete = 
        new System.Collections.Generic.List<int>();
    // Iterate through the Products.Rows property
    foreach (GridViewRow row in Products.Rows)
    {
        // Access the CheckBox
        CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
        if (cb != null && cb.Checked)
        {
            // Save the ProductID value for deletion
            // First, get the ProductID for the selected row
            int productID = 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);
        }
    }
    // Call the DeleteProductsWithTransaction method and show the Label 
    // if at least one row was deleted...
    if (productIDsToDelete.Count > 0)
    {
        ProductsBLL productAPI = new ProductsBLL();
        productAPI.DeleteProductsWithTransaction(productIDsToDelete);
        DeleteResults.Visible = true;
        // Rebind the data to the GridView
        Products.DataBind();
    }
}

更新的程式代碼會 List<T> 建立類型 int 為 (productIDsToDelete) ,並填 ProductID 入要刪除的值。 foreach循環之後,如果至少已選取一個產品,則會ProductsBLL呼叫 類別 s DeleteProductsWithTransaction 方法,並傳遞此清單。 也會顯示標籤 DeleteResults ,並將數據重新系結至 GridView (,讓新刪除的記錄不再顯示為網格線中的數據列) 。

圖 4 顯示已選取一些數據列以供刪除之後的 GridView。 圖 5 顯示在按兩下 [刪除選取的產品] 按鈕之後的畫面。 請注意,在圖 5 中, ProductID 已刪除記錄的值會顯示在 GridView 下方的 Label 中,而且這些數據列不再位於 GridView 中。

將會刪除選取的產品

圖 4:選取的產品將會刪除, (按兩下即可檢視完整大小的影像)

已刪除的產品 ProductID 值列在 GridView 下方

圖 5:已刪除的產品 ProductID 值列在 GridView 下方, (按兩下即可檢視完整大小的影像)

注意

若要測試 DeleteProductsWithTransaction 方法的不可部分完成性,請手動新增數據表中 Order Details 產品的專案,然後嘗試刪除該產品 (與其他專案) 。 當您嘗試刪除具有相關聯訂單的產品時,您會收到外鍵條件約束違規,但請注意其他選取的產品刪除如何復原。

摘要

建立批次刪除介面牽涉到新增具有複選框數據行的 GridView,以及按鍵 Web 控制項時,會將所有選取的數據列刪除為單一不可部分完成的作業。 在本教學課程中,我們會透過將上述兩個教學課程中的工作餅化來建置這類介面: 新增複選框的 GridView 數據行,並在 交易內包裝資料庫修改。 在第一個教學課程中,我們建立了具有複選框數據行的 GridView,並在後者中實作 BLL 中的方法,在傳遞List<T>ProductID值時,將它們全部刪除在交易的範圍內。

在下一個教學課程中,我們將建立介面來執行批次插入。

快樂的程序設計!

關於作者

Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET

特別感謝

本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的首席檢閱者是「前者 Giesenow」和「Teresa Murphy」。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。