Dávkové odstraňování (C#)
Zjistěte, jak odstranit více databázových záznamů v rámci jedné operace. Ve vrstvě uživatelského rozhraní vycházíme z vylepšeného objektu GridView vytvořeného v dřívějším kurzu. Ve vrstvě přístupu k datům zabalíme několik operací odstranění v rámci transakce, abychom zajistili, že všechna odstranění budou úspěšná nebo vrácená zpět.
Úvod
Předchozí kurz zkoumal, jak vytvořit rozhraní pro dávkové úpravy pomocí plně upravitelného objektu GridView. V situacích, kdy uživatelé často upravují mnoho záznamů najednou, bude rozhraní dávkové úpravy vyžadovat mnohem méně zpětných volání a kontextových přepínačů mezi klávesnicí a myší, což zlepší efektivitu koncového uživatele. Tato technika je podobně užitečná pro stránky, kde je běžné, že uživatelé odstraní mnoho záznamů najednou.
Každý, kdo používal online e-mailového klienta, už zná jedno z nejběžnějších rozhraní dávkového odstraňování: zaškrtávací políčka v každém řádku v mřížce s odpovídajícím tlačítkem Odstranit všechny zaškrtnuté položky (viz obrázek 1). Tento kurz je poměrně krátký, protože jsme již provedli veškerou tvrdou práci v předchozích kurzech při vytváření webového rozhraní a metody odstranění řady záznamů jako jedné atomické operace. V kurzu Přidání sloupce zaškrtávacích políček GridView jsme vytvořili GridView se sloupcem zaškrtávacích políček a v kurzu Obtékání úprav databáze v rámci transakce jsme vytvořili metodu v BLL, která by použila transakci k odstranění List<T>
ProductID
hodnoty. V tomto kurzu budeme stavět na našich předchozích prostředích a sloučit je, abychom vytvořili funkční příklad dávkového odstranění.
Obrázek 1: Každý řádek obsahuje zaškrtávací políčko (kliknutím zobrazíte obrázek v plné velikosti)
Krok 1: Vytvoření rozhraní pro odstraňování dávky
Vzhledem k tomu, že jsme již vytvořili rozhraní dávkového odstraňování v kurzu Přidání sloupce GridView zaškrtávacích políček , můžeme ho jednoduše zkopírovat do BatchDelete.aspx
, nikoli vytvořit od začátku. Začněte otevřením BatchDelete.aspx
stránky ve BatchData
složce a CheckBoxField.aspx
stránky ve EnhancedGridView
složce. Ze CheckBoxField.aspx
stránky přejděte do zobrazení Zdroj a zkopírujte značky mezi <asp:Content>
značky, jak je znázorněno na obrázku 2.
Obrázek 2: Zkopírování deklarativního CheckBoxField.aspx
kódu do schránky (kliknutím zobrazíte obrázek v plné velikosti)
Pak přejděte do zobrazení Zdroj v BatchDelete.aspx
a vložte obsah schránky do značek <asp:Content>
. Kód také zkopírujte a vložte z třídy code-behind v CheckBoxField.aspx.cs
souboru do třídy kódu na pozadí v BatchDelete.aspx.cs
systému ( DeleteSelectedProducts
obslužná rutina události Button s Click
, ToggleCheckState
metoda a Click
obslužné rutiny událostí pro CheckAll
tlačítka a UncheckAll
). Po zkopírování tohoto obsahu BatchDelete.aspx
by třída kódu na pozadí stránky měla obsahovat následující kód:
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);
}
}
Po zkopírování deklarativního kódu a zdrojového kódu chvíli vyzkoušejte BatchDelete.aspx
zobrazením v prohlížeči. Měli byste vidět GridView se seznamem prvních deseti produktů v GridView s každým řádkem se seznamem názvu produktu, kategorie a ceny spolu se zaškrtávacím políkem. Měla by existovat tři tlačítka: Zaškrtnout vše, Zrušit zaškrtnutí všech a Odstranit vybrané produkty. Kliknutím na tlačítko Zaškrtnout vše zaškrtnete všechna políčka, zatímco zaškrtnutí všech políček zrušíte. Kliknutím na Odstranit vybrané produkty se zobrazí zpráva se seznamem ProductID
hodnot vybraných produktů, ale produkty se ve skutečnosti neodstraní.
Obrázek 3: Rozhraní z CheckBoxField.aspx
bylo přesunuto do BatchDeleting.aspx
(kliknutím zobrazíte obrázek v plné velikosti)
Krok 2: Odstranění kontrolovaných produktů pomocí transakcí
Po úspěšném zkopírování rozhraní pro odstranění dávky do BatchDeleting.aspx
nástroje zbývá pouze aktualizovat kód tak, aby tlačítko Odstranit vybrané produkty odstranilo kontrolované produkty pomocí DeleteProductsWithTransaction
metody ve ProductsBLL
třídě . Tato metoda, přidaná v kurzu Obtékání úprav databáze v rámci transakce , přijímá jako vstup List<T>
ProductID
hodnoty a odstraní každou odpovídající ProductID
v rámci rozsahu transakce.
Obslužná rutina DeleteSelectedProducts
události Button s Click
aktuálně používá následující foreach
smyčku k iteraci jednotlivými řádky 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);
//............................................
}
}
Pro každý řádek je ProductSelector
ovládací prvek CheckBox Web programově odkazován. Pokud je zaškrtnuté, řádek s ProductID
se načte z DataKeys
kolekce a DeleteResults
vlastnost Popisek s Text
se aktualizuje tak, aby obsahovala zprávu o tom, že řádek byl vybrán k odstranění.
Výše uvedený kód ve skutečnosti neodstraní žádné záznamy, protože volání ProductsBLL
metody třídy s Delete
je okomentováno. Pokud by se tato logika odstranění použila, kód by odstranil produkty, ale ne v rámci atomické operace. To znamená, že pokud bylo několik prvních odstranění v sekvenci úspěšné, ale pozdější odstranění selhalo (možná kvůli porušení omezení cizího klíče), vyvolá se výjimka, ale tyto produkty, které už byly odstraněny, zůstanou odstraněné.
Abychom zajistili nedělitelnost, musíme místo toho použít metodu ProductsBLL
třídy s DeleteProductsWithTransaction
. Vzhledem k tomu, že tato metoda přijímá seznam ProductID
hodnot, musíme tento seznam nejprve zkompilovat z mřížky a pak ho předat jako parametr. Nejprve vytvoříme instanci List<T>
typu int
. V rámci smyčky foreach
musíme k tomuto List<T>
objektu přidat hodnoty vybraných produktůProductID
. Po smyčce se musí List<T>
předat ProductsBLL
metodě třídy s DeleteProductsWithTransaction
. Aktualizujte obslužnou rutinu DeleteSelectedProducts
události Button s Click
následujícím kódem:
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();
}
}
Aktualizovaný kód vytvoří List<T>
typ int
(productIDsToDelete
) a naplní ho hodnotami, ProductID
které se mají odstranit. Po smyčce foreach
, pokud je vybrán alespoň jeden produkt, ProductsBLL
je volána metoda třídy s DeleteProductsWithTransaction
a předána tento seznam. Zobrazí DeleteResults
se také popisek a data se přeskočí do objektu GridView (aby se nově odstraněné záznamy už nezobrazovaly jako řádky v mřížce).
Obrázek 4 znázorňuje GridView po výběru počtu řádků k odstranění. Obrázek 5 znázorňuje obrazovku hned po kliknutí na tlačítko Odstranit vybrané produkty. Všimněte si, že na obrázku ProductID
5 se hodnoty odstraněných záznamů zobrazují v popisku pod objektem GridView a tyto řádky už nejsou v objektu GridView.
Obrázek 4: Vybrané produkty budou odstraněny (kliknutím zobrazíte obrázek v plné velikosti)
Obrázek 5: Hodnoty Odstraněné produkty ProductID
jsou uvedené pod objektem GridView (kliknutím zobrazíte obrázek v plné velikosti).
Poznámka
Pokud chcete otestovat DeleteProductsWithTransaction
nedělitelnost metody, ručně přidejte položku pro produkt v Order Details
tabulce a pak se pokuste tento produkt (spolu s dalšími položkami) odstranit. Při pokusu o odstranění produktu s přidruženou objednávkou se zobrazí porušení omezení cizího klíče, ale všimněte si, jak se odstranění ostatních vybraných produktů vrátí zpět.
Souhrn
Vytvoření rozhraní dávkového odstraňování zahrnuje přidání GridView se sloupcem zaškrtávacích políček a webového ovládacího prvku Button, který po kliknutí odstraní všechny vybrané řádky jako jednu atomické operace. V tomto kurzu jsme vytvořili takové rozhraní tak, že jsme společně vytvořili práci provedenou ve dvou předchozích kurzech, Přidání sloupce GridView zaškrtávacích políček a Zabalení úprav databáze v rámci transakce. V prvním kurzu jsme vytvořili GridView se sloupcem zaškrtávacích políček a ve druhém jsme implementovali metodu v BLL, která při předání List<T>
ProductID
hodnoty odstranila všechny v rámci rozsahu transakce.
V dalším kurzu vytvoříme rozhraní pro dávkové vkládání.
Všechno nejlepší na programování!
O autorovi
Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho zastihnout na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na adrese http://ScottOnWriting.NET.
Zvláštní poděkování
Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty pro tento kurz byly Hilton Giesenow a Teresa Murphy. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.