在ASP.NET 2.0中操作數(shù)據(jù)之六十三:GridView實現(xiàn)批量刪除數(shù)據(jù)
導(dǎo)言:
在前面的教程,我們用GridView創(chuàng)建了一個批編輯界面。在用戶需要一次性編輯多條記錄的情況下,批編輯界面很有用。同理,當(dāng)用戶需要同時刪除多條記錄時,該技術(shù)也很有用.
如果你使用過郵件系統(tǒng)的話,你應(yīng)該對這種最常見的批刪除界面很熟悉:界面里每一行都包含一個checkbox,此外,還有一個“Delete All Checked Items”按鈕(如圖1).本教程比較短,因為我們在前面的教程已經(jīng)完成大體的框架,在前面的第50章《為GridView控件添加Checkbox》里我們創(chuàng)建了一個包含一個checkboxes列的GridView控件;而在61章《在事務(wù)里對數(shù)據(jù)庫修改進(jìn)行封裝》里,我們在BLL業(yè)務(wù)邏輯層里創(chuàng)建了一個方法,該方法使用事務(wù)來刪除基于ProductID 的記錄.在本教程,我們將整合這些內(nèi)容來創(chuàng)建一個處理批刪除的示例.
圖1:每一行都包含一個Checkbox
第一步:創(chuàng)建批刪除界面
由于我們在第52章已經(jīng)創(chuàng)建了一個批刪除界面,因此我們可以簡單的將其拷貝到BatchDelete.aspx頁面。首先,打開BatchData文件夾里的BatchDelete.aspx頁面,以及EnhancedGridView文件夾里的CheckBoxField.aspx頁面。在CheckBoxField.aspx頁面,切換到Source模式,將<asp:Content>標(biāo)簽里的代碼進(jìn)行復(fù)制.
圖2:復(fù)制CheckBoxField.aspx頁面里的聲明代碼
然后,切換到BatchDelete.aspx頁面的Source模式,將代碼粘貼到<asp:Content>標(biāo)簽里.同理,將CheckBoxField.aspx.cs里面的后臺代碼拷貝到BatchDelete.aspx.cs里.(具體來說,就是將DeleteSelectedProducts按鈕的Click event事件、ToggleCheckState方法、CheckAll 和 UncheckAll按鈕的Click event事件)。完成拷貝后,BatchDelete.aspx頁面的后臺代碼類應(yīng)該包含下面的代碼:
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); } }
完成上述工作后,花幾分鐘在瀏覽器里測試該頁面.你應(yīng)該首先看到一個GridView控件列出了前10個產(chǎn)品,每行列出了產(chǎn)品的name, category,price以及一個checkbox. 同時應(yīng)該有3個按鈕“Check All”, “Uncheck All”和“Delete Selected Products”.點“Check All”按鈕將會選中所有的checkboxes;而“Uncheck All”按鈕將釋放所有的
checkboxes;點“Delete Selected Products”的話將顯示一個消息,列出選中的產(chǎn)品的ProductID值,不過并不會真的刪除產(chǎn)品.
圖3:CheckBoxField.aspx頁面的界面搬到了BatchDeleting.aspx頁面
第二步:在事務(wù)里刪除選中的產(chǎn)品
完成界面后,剩下的事情是更新代碼,以便當(dāng)點擊“Delete Selected Products”按鈕時,使用ProductsBLL class類里的DeleteProductsWithTransaction方法來刪除選中的產(chǎn)品.該方法是我們在第61章《在事務(wù)里對數(shù)據(jù)庫修改進(jìn)行封裝》里添加的,它接受一系列的ProductID值,然后在一個事務(wù)里將刪除對應(yīng)的ProductID的記錄.
DeleteSelectedProducts按鈕的Click事件目前使用的foreach循環(huán)如下:
// 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控件,如果它被選中,從DataKeys collection集獲取該產(chǎn)品的ProductID值,然后更新DeleteResults控件的Text屬性以顯示要刪除該行.
上面的代碼并不會真的刪除任何的記錄,因為在ProductsBLL class類里我們只是注釋出了如何使用Delete方法。 不過就算實際地運(yùn)用了這些刪除邏輯,這些代碼雖然可以刪除產(chǎn)品但沒有運(yùn)用原子操作.也就是說,如果按順序?qū)︻^幾個產(chǎn)品刪除成功,如果接下來的某個產(chǎn)品刪除失敗(比如可能是違背里外鍵約束),那么將拋出一個異常,但是前面的刪除操作并不會回滾.
為了保證使用原子操作,我們將轉(zhuǎn)為使用ProductsBLLclass類的DeleteProductsWithTransaction method方法.由于該方法接受一系列的ProductID值,
我們首先需要編譯這一系列的值,再將其作為參數(shù)傳遞出去.我們首先創(chuàng)建一個int類型的List<T>的實例,在foreach循環(huán)里我們需要將產(chǎn)品的ProductID值添加給List<T>,結(jié)束循環(huán)后,List<T>將傳遞給ProductsBLL class類的DeleteProductsWithTransaction method方法,用下面的代碼對DeleteSelectedProducts按鈕的Click事件處理器進(jìn)行更新:
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(); } }
上述代碼創(chuàng)建了一個int類型的List<T>(也就是productIDsToDelete),并用ProductID值對其進(jìn)行填充,foreach循環(huán)結(jié)束后,如果至少選中了一個產(chǎn)品,將調(diào)用ProductsBLL 類的DeleteProductsWithTransaction method方法,并傳遞該List。名為DeleteResults的Label控件也將顯示出來;數(shù)據(jù)重新綁定到GridView(自然,剛刪除掉的記錄將不會顯示出來).
圖4里,我們選擇幾個產(chǎn)品以刪除;圖5顯示的是點擊“Delete Selected Products”按鈕后的界面.注意,在Label控件里顯示的已經(jīng)刪除的產(chǎn)品的ProductID值,而這些產(chǎn)品已經(jīng)刪除掉了,并沒有出現(xiàn)在GridView控件里.
圖4:選中的產(chǎn)品將被刪除
圖5:被刪除產(chǎn)品的ProductID值出現(xiàn)的GridView下面的Label控件里
注意:為驗證DeleteProductsWithTransaction method方法的原子操作,你可以為某個產(chǎn)品在Order Details表里手動添加一個條目,然后嘗試刪除該產(chǎn)品(當(dāng)然與其它產(chǎn)品一起刪除).這將會違背外鍵約束,注意對其它產(chǎn)品的刪除操作是如何回滾的.
總結(jié):
創(chuàng)建一個批刪除界面的話,我們需要創(chuàng)建一個包含checkboxes列的GridView控件,以及Button Web控件。當(dāng)點擊該按鈕時,我們將刪除多個產(chǎn)品當(dāng)作一個單一原子操作.在本文,我們創(chuàng)建的界面整合了以前的2個章節(jié)的內(nèi)容.
在下一篇,我們考察如何創(chuàng)建一個批插入的界面
祝編程快樂!
作者簡介
本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創(chuàng)始人,自1998年以來一直應(yīng)用 微軟Web技術(shù)。大家可以點擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數(shù)據(jù)教程》,希望對大家的學(xué)習(xí)ASP.NET有所幫助。
相關(guān)文章
Microsoft .Net Remoting系列教程之二:Marshal、Disconnect與生命周期以及跟蹤服務(wù)
本文主要講解.Net Remoting中Marshal、Disconnect與生命周期以及跟蹤服務(wù),需要的朋友可以參考下。2016-05-05.Net Core服務(wù)治理Consul自動擴(kuò)展和服務(wù)調(diào)用
這篇文章介紹了.Net Core服務(wù)治理Consul自動擴(kuò)展和服務(wù)調(diào)用,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01在ASP.NET 2.0中操作數(shù)據(jù)之五十三:在Data Web控件顯示二進(jìn)制數(shù)據(jù)
本文主要介紹在ASP.NET 2.0中直接顯示PDF超鏈接的方法,以及如何把已二進(jìn)制數(shù)據(jù)形式保存的圖片顯示在GridView中的方法,雖然這種方法在實際開發(fā)中很少用,但還是值得學(xué)習(xí)一下。2016-05-05在ASP.NET 2.0中操作數(shù)據(jù)之四十一:DataList和Repeater數(shù)據(jù)分頁
DataList 和Repeater 都沒有提供內(nèi)置的分頁和排序功能,本文主要介紹利用PagedDataSource實現(xiàn)DataList和Repeater數(shù)據(jù)分頁。2016-05-05寫給初學(xué)asp.net的新人們 新手學(xué)習(xí)經(jīng)驗
IT=挨踢,這是IT人的自嘲,進(jìn)入IT行業(yè)是有四五年了,也算得上是一個“老人”了吧,見了不少新人,面試了不少新人,也帶了一些新人,多多少少還是有點發(fā)言權(quán)的。2010-05-05在ASP.NET 2.0中操作數(shù)據(jù)之四十三:DataList和Repeater數(shù)據(jù)排序(二)
上篇已經(jīng)介紹了DropDownList隱式使用ViewState,本文主要介紹詳細(xì)介紹直接使用ViewState存儲排序的條件,并配合上一頁、下一頁按鈕,實現(xiàn)DataList和Repeater自定義排序的功能。2016-05-05在ASP.NET 2.0中操作數(shù)據(jù)之十一:基于數(shù)據(jù)的自定義格式化
GridView, DetailsView, FormView的格式自定義可以有多種方法, 在本文中我們將用DataBound 和 RowDataBound兩種事件來完成,下面主要演示了貨幣、加粗、斜體、高亮的數(shù)據(jù)格式化。2016-05-05在ASP.NET 2.0中操作數(shù)據(jù)之五十一:從GridView的頁腳插入新記錄
本文介紹在ASP.NET 2.0中如何在GridView的頁腳動態(tài)插入一行新記錄,要顯示頁腳行只需要設(shè)置ShowFooter屬性為true。我們可以這樣對頁腳行進(jìn)行用戶定制:將每一列轉(zhuǎn)換成TemplateField,并在其FooterTemplate模板定制插入界面。2016-05-05在ASP.NET 2.0中操作數(shù)據(jù)之二十四:分頁和排序報表數(shù)據(jù)
本文主要介紹ASP.NET 2.0中使用GirdView控件呈現(xiàn)數(shù)據(jù)時如何實現(xiàn)分頁和排序功能的,希望對大家有所幫助。2016-05-05