Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Lär dig hur du tar bort flera databasposter i en enda åtgärd. I användargränssnittsskiktet bygger vi på en förbättrad GridView som skapats i en tidigare självstudie. I dataåtkomstlagret omsluter vi flera borttagningsåtgärder i en transaktion för att säkerställa att alla borttagningar lyckas eller att alla borttagningar återställs.
Inledning
I den föregående självstudien utforskades hur du skapar ett batchredigeringsgränssnitt med hjälp av ett fullständigt redigerbart GridView. I situationer där användare ofta redigerar många poster samtidigt kräver ett batchredigeringsgränssnitt mycket färre postbacks och kontextväxlar från tangentbord till mus, vilket förbättrar slutanvändarens effektivitet. Den här tekniken är lika användbar för sidor där det är vanligt att användare tar bort många poster på en och samma resa.
Alla som har använt en e-postklient online är redan bekant med ett av de vanligaste batchborttagningsgränssnitten: en kryssruta i varje rad i ett rutnät med motsvarande knappen Ta bort alla markerade objekt (se bild 1). Den här handledningen är ganska kort eftersom vi redan har utfört allt det tunga arbetet i tidigare handledningar för att skapa både det webbaserade gränssnittet och en metod för att ta bort en följd av poster som en enda atomisk åtgärd. I självstudien Lägga till en GridView-kolumn med kryssrutor skapade vi en GridView med en kolumn med kryssrutor och i självstudiekursen Omsluta databasändringar i en transaktion skapade vi en metod i BLL som skulle använda en transaktion för att ta bort en List<T> med ProductID värden. I den här handledningen bygger vi vidare på och sammanfogar våra tidigare erfarenheter för att skapa ett fungerande exempel på batchborttagning.
Bild 1: Varje rad innehåller en kryssruta (Klicka om du vill visa en bild i full storlek)
Steg 1: Skapa batchborttagningsgränssnittet
Eftersom vi redan har skapat batchborttagningsgränssnittet i självstudien Lägga till en GridView-kolumn med kryssrutor kan vi enkelt kopiera det till BatchDelete.aspx i stället för att skapa det från grunden. Börja med att öppna sidan BatchDelete.aspx i BatchData mappen och CheckBoxField.aspx sidan i EnhancedGridView mappen. Från sidan CheckBoxField.aspx går du till källvyn och kopierar pålägget mellan taggarna <asp:Content> enligt bild 2.
Bild 2: Kopiera den deklarativa markeringen av CheckBoxField.aspx till urklippet (Klicka för att visa en bild i full storlek)
Gå sedan till källvyn i BatchDelete.aspx och klistra in innehållet från urklipp i taggarna <asp:Content>. Kopiera och klistra också in koden inifrån klassen code-behind i CheckBoxField.aspx.cs i klassen code-behind i BatchDelete.aspx.cs ( DeleteSelectedProducts button-händelsehanteraren Click , ToggleCheckState metoden och Click händelsehanterarna för CheckAll knapparna och UncheckAll ). När du har kopierat över det här innehållet BatchDelete.aspx ska sidans kod-bakom-klass innehålla följande kod:
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);
}
}
När du har kopierat över deklarativ kod och källkod tar du en stund att testa BatchDelete.aspx genom att visa den via en webbläsare. Du bör se en GridView-lista över de första tio produkterna i en GridView med varje rad som visar produktens namn, kategori och pris tillsammans med en kryssruta. Det bör finnas tre knappar: Markera Alla, Avmarkera Alla och Ta bort markerade produkter. Om du klickar på knappen Markera alla markeras alla kryssrutor, medan Avmarkera alla avmarkerar alla kryssrutor. När du klickar på Ta bort markerade produkter visas ett meddelande som visar ProductID värdena för de valda produkterna, men som inte tar bort produkterna.
Bild 3: Gränssnittet från CheckBoxField.aspx har flyttats till BatchDeleting.aspx (Klicka om du vill visa en bild i full storlek)
Steg 2: Ta bort de kontrollerade produkterna med hjälp av transaktioner
När batchborttagningsgränssnittet har kopierats till BatchDeleting.aspxär allt som återstår att uppdatera koden så att knappen Ta bort markerade produkter tar bort de kontrollerade produkterna med hjälp av DeleteProductsWithTransaction metoden i ProductsBLL klassen. Den här metoden, som lades till i handledningen Omsluta databasändringar i en transaktion, tar emot List<T> av ProductID värden som indata och tar bort varje motsvarande ProductID inom intervallet för en transaktion.
Händelsehanteraren DeleteSelectedProducts för Button Click använder för närvarande följande foreach loop för att iterera genom varje GridView-rad:
// 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);
//............................................
}
}
För varje rad ProductSelector refereras checkbox-webbkontrollen programmatiskt. Om den är markerad hämtas raden ProductID från DataKeys samlingen och DeleteResults etikettens egenskap Text uppdateras för att inkludera ett meddelande som anger att raden har valts för borttagning.
Koden ovan tar faktiskt inte bort några poster eftersom anropet till ProductsBLL klassens Delete -metod kommenteras ut. Om den här borttagningslogiken skulle tillämpas skulle koden ta bort produkterna men inte inom en atomisk åtgärd. Om de första borttagningarna i sekvensen lyckades, men ett senare misslyckades (kanske på grund av en överträdelse av begränsningen för sekundärnyckel), skulle ett undantag genereras, men de produkter som redan har tagits bort skulle förblir borttagna.
För att säkerställa atomitet måste vi i stället använda ProductsBLL metoden class s DeleteProductsWithTransaction . Eftersom den här metoden accepterar en lista med ProductID värden måste vi först kompilera den här listan från rutnätet och sedan skicka den som en parameter. Först skapar vi en instans av typen List<T>int. I loopen foreach måste vi lägga till de valda produktvärdena ProductID i den här List<T>. Efter loopen måste detta List<T> skickas till ProductsBLL klassens DeleteProductsWithTransaction -metod.
DeleteSelectedProducts Uppdatera knappens Click händelsehanterare med följande kod:
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();
}
}
Den uppdaterade koden skapar en List<T> av typen int (productIDsToDelete) och fyller den med de värden som ProductID ska tas bort. Efter loopen foreach, om det finns minst en vald produkt, anropas ProductsBLL-klassens DeleteProductsWithTransaction-metod och skickas den här listan. Etiketten DeleteResults visas också och data återställs till GridView (så att de nyligen borttagna posterna inte längre visas som rader i rutnätet).
Bild 4 visar GridView när ett antal rader har valts för borttagning. Bild 5 visar skärmen direkt efter att knappen Ta bort markerade produkter har klickats på. Observera att värdena för de borttagna posterna ProductID i bild 5 visas i etiketten under GridView och att dessa rader inte längre finns i GridView.
Bild 4: De markerade produkterna tas bort (klicka om du vill visa en bild i full storlek)
Bild 5: Värdena för borttagna produkter ProductID visas under GridView (klicka om du vill visa en bild i full storlek)
Anmärkning
Om du vill testa DeleteProductsWithTransaction metodens atomitet lägger du manuellt till en post för en produkt i Order Details tabellen och försöker sedan ta bort produkten (tillsammans med andra). Du får en överträdelse av främmande nyckelbegränsning när du försöker ta bort produkten med en associerad order, men observera hur de andra valda produkternas radering återställs.
Sammanfattning
När du skapar ett batchborttagningsgränssnitt måste du lägga till en GridView med en kolumn med kryssrutor och en knappwebbkontroll som när du klickar på den tar bort alla markerade rader som en enda atomisk åtgärd. I den här självstudien har vi skapat ett sådant gränssnitt genom att sammanställa arbete som utförts i två tidigare självstudier, lägga till en GridView-kolumn med kryssrutor och omsluta databasändringar i en transaktion. I den första självstudien skapade vi en GridView med en kolumn med kryssrutor och senare implementerade vi en metod i BLL:n som, när den fick en List<T> med ProductID värden, tog bort dem alla inom omfånget för en transaktion.
I nästa handledning skapar vi ett gränssnitt för att utföra batchinfogningar.
Lycka till med programmerandet!
Om författaren
Scott Mitchell, författare till sju ASP/ASP.NET-böcker och grundare av 4GuysFromRolla.com, har arbetat med Microsofts webbtekniker sedan 1998. Scott arbetar som oberoende konsult, tränare och författare. Hans senaste bok är Sams Teach Yourself ASP.NET 2.0 på 24 timmar. Han kan nås på mitchell@4GuysFromRolla.com.
Särskilt tack till
Den här självstudieserien granskades av många användbara granskare. Huvudgranskare för den här handledningen var Hilton Giesenow och Teresa Murphy. Vill du granska mina kommande MSDN-artiklar? Om så är fallet, hör av dig på mitchell@4GuysFromRolla.com.