Udostępnij za pośrednictwem


Usuwanie w partiach (C#)

Autor: Scott Mitchell

Pobierz plik PDF

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.

Każdy wiersz zawiera pole wyboru

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.

Skopiuj deklaratywne znaczniki CheckBoxField.aspx do Schowka

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 (DeleteSelectedProductsprocedura obsługi zdarzeń przyciskuClick, ToggleCheckState metoda i programy obsługi zdarzeń dla CheckAll przycisków i ClickUncheckAll). 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.

Interfejs z CheckBoxField.aspx został przeniesiony do BatchDeleting.aspx

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.aspxprogramu 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.

Wybrane produkty zostaną usunięte

Rysunek 4. Usunięte wybrane produkty (kliknij, aby wyświetlić obraz pełnowymiarowy)

Wartości ProductID usuniętych produktów są wymienione poniżej elementu GridView

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.