Usuwanie w partiach (C#)
Dowiedz się, jak usunąć wiele rekordów bazy danych w ramach jednej operacji. W warstwie interfejsu użytkownika bazujemy na ulepszonym elemedycie GridView utworzonym we wcześniejszym samouczku. W warstwie dostępu do danych opakowujemy wiele operacji usuwania w ramach transakcji, aby upewnić się, że wszystkie operacje usuwania zakończyły się pomyślnie lub wszystkie usunięcia zostały wycofane.
Wprowadzenie
W poprzednim samouczku przedstawiono sposób tworzenia interfejsu edycji wsadowej przy użyciu w pełni edytowalnego elementu GridView. W sytuacjach, w których użytkownicy często edytują wiele rekordów jednocześnie, interfejs edycji wsadowej będzie wymagał znacznie mniejszej liczby zwrotów i przełączników kontekstowych klawiatury do myszy, co zwiększa wydajność użytkownika końcowego. Ta technika jest podobnie przydatna w przypadku stron, na których użytkownicy często usuwają wiele rekordów w jednym przejściu.
Każda osoba, która korzystała z klienta poczty e-mail online, zna już jeden z najbardziej typowych interfejsów usuwania partii: pole wyboru w każdym wierszu w siatce z odpowiednim przyciskiem Usuń wszystkie zaznaczone elementy (zobacz Rysunek 1). Ten samouczek jest dość krótki, ponieważ już wykonaliśmy całą ciężką pracę w poprzednich samouczkach podczas tworzenia zarówno interfejsu internetowego, jak i metody usuwania serii rekordów jako pojedynczej operacji atomowej. W samouczku Dodawanie kolumny Pola wyboru elementu GridView utworzyliśmy kontrolkę GridView z kolumną pól wyboru i w samouczku Zawijanie modyfikacji bazy danych w ramach transakcji utworzyliśmy metodę w usłudze BLL, która będzie używać transakcji do usuwania List<T>
ProductID
wartości. W tym samouczku skompilujemy i scalimy nasze poprzednie środowiska, aby utworzyć przykład usuwania partii roboczej.
Rysunek 1. Każdy wiersz zawiera pole wyboru (kliknij, aby wyświetlić obraz pełnowymiarowy)
Krok 1. Tworzenie interfejsu usuwania wsadowego
Ponieważ już utworzyliśmy interfejs usuwania wsadowego w samouczku Dodawanie kolumny pola wyboru elementu GridView , możemy po prostu skopiować go do BatchDelete.aspx
, zamiast tworzyć go od podstaw. Zacznij od otwarcia strony w BatchData
folderze i CheckBoxField.aspx
na stronie w folderzeEnhancedGridView
.BatchDelete.aspx
CheckBoxField.aspx
Na stronie przejdź do widoku Źródło i skopiuj znaczniki między tagami<asp:Content>
, jak pokazano na rysunku 2.
Rysunek 2. Skopiuj deklaratywne znaczniki CheckBoxField.aspx
do Schowka (kliknij, aby wyświetlić obraz pełnowymiarowy)
Następnie przejdź do widoku Źródło i BatchDelete.aspx
wklej zawartość schowka w tagach <asp:Content>
. Skopiuj i wklej kod z klasy w kodzie w klasie w pliku w CheckBoxField.aspx.cs
klasie code-behind w programie BatchDelete.aspx.cs
(DeleteSelectedProducts
procedura obsługi zdarzeń przyciskuClick
, ToggleCheckState
metoda i programy obsługi zdarzeń dla CheckAll
przycisków i Click
UncheckAll
). Po skopiowaniu tej zawartości BatchDelete.aspx
klasa s code-behind strony powinna zawierać następujący 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);
}
}
Po skopiowaniu deklaratywnego znaczników i kodu źródłowego poświęć chwilę na przetestowanie BatchDelete.aspx
, przeglądając go za pośrednictwem przeglądarki. Element GridView powinien zawierać listę pierwszych dziesięciu produktów w elemecie GridView z każdym wierszem zawierającym nazwę produktu, kategorię i cenę wraz z polem wyboru. Powinny istnieć trzy przyciski: Zaznacz wszystko, Usuń zaznaczenie pola wyboru Wszystkie i Usuń wybrane produkty. Kliknięcie przycisku Zaznacz wszystko zaznacz wszystkie pola wyboru, a zaznaczenie pola wyboru Usuń zaznaczenie pola wyboru Wszystkie jest zaznaczone. Kliknięcie pozycji Usuń wybrane produkty powoduje wyświetlenie komunikatu zawierającego listę ProductID
wartości wybranych produktów, ale nie powoduje usunięcia produktów.
Rysunek 3. Interfejs z CheckBoxField.aspx
został przeniesiony do BatchDeleting.aspx
(kliknij, aby wyświetlić obraz pełnowymiarowy)
Krok 2. Usuwanie zaznaczonych produktów przy użyciu transakcji
Po pomyślnym skopiowaniu interfejsu usuwania wsadowego do BatchDeleting.aspx
programu wszystkie pozostałe elementy należy zaktualizować kod, aby przycisk Usuń wybrane produkty usuwa zaznaczone produkty przy użyciu DeleteProductsWithTransaction
metody w ProductsBLL
klasie. Ta metoda, dodana w samouczku Zawijanie modyfikacji bazy danych w ramach transakcji , akceptuje jako dane wejściowe List<T>
ProductID
wartości i usuwa każdy odpowiadający ProductID
zakresowi transakcji.
Procedura DeleteSelectedProducts
obsługi zdarzeń przycisku Click
używa obecnie następującej foreach
pętli do iterowania poszczególnych wierszy 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);
//............................................
}
}
Dla każdego wiersza kontrolka ProductSelector
sieci Web CheckBox jest programowo przywoływana. Jeśli jest zaznaczone, wiersz s ProductID
jest pobierany z DataKeys
kolekcji, a DeleteResults
właściwość Etykieta Text
jest aktualizowana w celu uwzględnienia komunikatu wskazującego, że wiersz został wybrany do usunięcia.
Powyższy kod nie usuwa żadnych rekordów, ponieważ wywołanie ProductsBLL
metody klasy jest Delete
komentowane. Gdyby ta logika usuwania została zastosowana, kod usunąłby produkty, ale nie w ramach operacji niepodzielnej. Oznacza to, że jeśli pierwsze kilka operacji usuwania w sekwencji zakończyło się pomyślnie, ale później nie powiodło się (być może z powodu naruszenia ograniczenia klucza obcego), zostanie zgłoszony wyjątek, ale usunięte produkty pozostaną usunięte.
Aby zapewnić niepodzielność, musimy zamiast tego użyć ProductsBLL
metody klasy s DeleteProductsWithTransaction
. Ponieważ ta metoda akceptuje listę ProductID
wartości, musimy najpierw skompilować tę listę z siatki, a następnie przekazać ją jako parametr. Najpierw utworzymy wystąpienie List<T>
typu int
. foreach
W pętli musimy dodać do tej List<T>
pętli wybrane wartości produktów ProductID
. Po pętli należy przekazać tę List<T>
pętlę ProductsBLL
do metody s DeleteProductsWithTransaction
klasy. Zaktualizuj procedurę obsługi zdarzeń DeleteSelectedProducts
przycisku Click
przy użyciu następującego kodu:
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();
}
}
Zaktualizowany kod tworzy List<T>
typ int
(productIDsToDelete
) i wypełnia go wartościami ProductID
do usunięcia. foreach
Po pętli, jeśli wybrano co najmniej jeden produkt, ProductsBLL
metoda klasy jest DeleteProductsWithTransaction
wywoływana i przekazywana tej listy. Etykieta DeleteResults
jest również wyświetlana, a dane są ponownie przesyłane do kontrolki GridView (dzięki czemu nowo usunięte rekordy nie są już wyświetlane jako wiersze w siatce).
Rysunek 4 przedstawia element GridView po wybraniu liczby wierszy do usunięcia. Rysunek 5 przedstawia ekran natychmiast po kliknięciu przycisku Usuń wybrane produkty. Zwróć uwagę, że na rysunku 5 ProductID
wartości usuniętych rekordów są wyświetlane w obszarze Etykieta pod kontrolką GridView, a te wiersze nie znajdują się już w siatce.
Rysunek 4. Usunięte wybrane produkty (kliknij, aby wyświetlić obraz pełnowymiarowy)
Rysunek 5. Wartości usuniętych produktów ProductID
znajdują się poniżej widoku GridView (kliknij, aby wyświetlić obraz pełnowymiarowy)
Uwaga
Aby przetestować DeleteProductsWithTransaction
niepodzielność metody, ręcznie dodaj wpis dla produktu w Order Details
tabeli, a następnie spróbuj usunąć ten produkt (wraz z innymi). Podczas próby usunięcia produktu ze skojarzonym zamówieniem otrzymasz naruszenie ograniczeń klucza obcego, ale zwróć uwagę na sposób wycofania pozostałych wybranych produktów.
Podsumowanie
Tworzenie interfejsu usuwania wsadowego obejmuje dodanie kontrolki GridView z kolumną pól wyboru i kontrolką Sieci Web przycisku, która po kliknięciu spowoduje usunięcie wszystkich zaznaczonych wierszy jako pojedynczej operacji niepodzielnej. W tym samouczku utworzyliśmy taki interfejs, łącząc pracę wykonaną w dwóch poprzednich samouczkach, dodając kolumnę GridView pól wyboru i zawijając modyfikacje bazy danych w ramach transakcji. W pierwszym samouczku utworzyliśmy element GridView z kolumną pól wyboru, a w drugim zaimplementowaliśmy metodę w usłudze BLL, która po przekazaniu List<T>
ProductID
wartości usunęła je wszystkie w zakresie transakcji.
W następnym samouczku utworzymy interfejs do wykonywania wstawiania wsadowego.
Szczęśliwe programowanie!
Informacje o autorze
Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Można do niego dotrzeć pod adresem mitchell@4GuysFromRolla.com. Lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.
Specjalne podziękowania
Ta seria samouczków została sprawdzona przez wielu pomocnych recenzentów. Recenzenci w tym samouczku byli Hilton Giesenow i Teresa Murphy. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.