Поделиться через


Пакетное удаление (VB)

Скотт Митчелл

Загрузить PDF-файл

Узнайте, как удалить несколько записей базы данных за одну операцию. На уровне пользовательского интерфейса мы опираемся на расширенный GridView, созданный в предыдущем руководстве. На уровне доступа к данным мы создадим оболочку для нескольких операций удаления в рамках транзакции, чтобы гарантировать успешное удаление или откат всех удалений.

Введение

В предыдущем руководстве было описано, как создать интерфейс пакетного редактирования с помощью полностью редактируемого элемента GridView. В ситуациях, когда пользователи обычно редактируют сразу несколько записей, интерфейс пакетного редактирования потребует гораздо меньше обратных передач и переключений контекста с клавиатуры на мышь, тем самым повышая эффективность работы конечного пользователя. Этот метод также полезен для страниц, где пользователи часто удаляют несколько записей за один раз.

Любой пользователь, использующий почтовый клиент, уже знаком с одним из наиболее распространенных интерфейсов пакетного удаления: флажком в каждой строке сетки с соответствующей кнопкой Удалить все проверенные элементы (см. рис. 1). Это руководство довольно короткое, так как мы уже выполнили всю тяжелую работу в предыдущих руководствах по созданию веб-интерфейса и метода удаления ряда записей в виде одной атомарной операции. В руководстве Добавление столбца Флажков GridView мы создали GridView со столбцом флажков, а в учебнике Упаковка изменений базы данных в рамках транзакции мы создали метод в BLL, который будет использовать транзакцию для удаления значений List<T>ProductID . В этом руководстве мы создадим и объединим предыдущий опыт, чтобы создать рабочий пример удаления пакета.

Каждая строка содержит флажок

Рис. 1. Каждая строка содержит флажок (щелкните для просмотра полноразмерного изображения)

Шаг 1. Создание интерфейса пакетного удаления

Так как мы уже создали интерфейс пакетного удаления в учебнике Добавление столбца флажков GridView , мы можем просто скопировать его в BatchDelete.aspx , а не создавать с нуля. Начните с открытия страницы BatchDelete.aspx в папке BatchData и страницы CheckBoxField.aspx в папке EnhancedGridView . На странице перейдите CheckBoxField.aspx в представление Источник и скопируйте разметку между тегами, как показано на <asp:Content> рисунке 2.

Копирование декларативной разметки CheckBoxField.aspx в буфер обмена

Рис. 2. Копирование декларативной разметки CheckBoxField.aspx в буфер обмена (щелкните для просмотра полноразмерного изображения)

Затем перейдите к представлению Источник в и вставьте BatchDelete.aspx содержимое буфера обмена в <asp:Content> теги. Кроме того, скопируйте и вставьте код из класса кода программной части в CheckBoxField.aspx.vb классе кода программной части в BatchDelete.aspx.vb ( DeleteSelectedProducts обработчик событий Button Click , ToggleCheckState метод и Click обработчики событий для CheckAll и UncheckAll Button). После копирования этого содержимого BatchDelete.aspx класс кода программной части страницы должен содержать следующий код:

Partial Class BatchData_BatchDelete
    Inherits System.Web.UI.Page
    Protected Sub DeleteSelectedProducts_Click(sender As Object, e As EventArgs) _
        Handles DeleteSelectedProducts.Click
        
        Dim atLeastOneRowDeleted As Boolean = False
        ' Iterate through the Products.Rows property
        For Each row As GridViewRow In Products.Rows
            ' Access the CheckBox
            Dim cb As CheckBox = row.FindControl("ProductSelector")
            If cb IsNot Nothing AndAlso cb.Checked Then
                ' Delete row! (Well, not really...)
                atLeastOneRowDeleted = True
                ' First, get the ProductID for the selected row
                Dim productID As Integer = _
                    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 ...
                ' Dim productAPI As New ProductsBLL
                ' productAPI.DeleteProduct(productID)
                '............................................
            End If
        Next
        ' Show the Label if at least one row was deleted...
        DeleteResults.Visible = atLeastOneRowDeleted
    End Sub
    Private Sub ToggleCheckState(ByVal checkState As Boolean)
        ' Iterate through the Products.Rows property
        For Each row As GridViewRow In Products.Rows
            ' Access the CheckBox
            Dim cb As CheckBox = row.FindControl("ProductSelector")
            If cb IsNot Nothing Then
                cb.Checked = checkState
            End If
        Next
    End Sub
    Protected Sub CheckAll_Click(sender As Object, e As EventArgs) _
        Handles CheckAll.Click
        ToggleCheckState(True)
    End Sub
    Protected Sub UncheckAll_Click(sender As Object, e As EventArgs) _
        Handles UncheckAll.Click
        ToggleCheckState(False)
    End Sub
End Class

После копирования декларативной разметки и исходного кода найдите время для тестирования BatchDelete.aspx , просмотрев его в браузере. Вы увидите в GridView список первых десяти продуктов в GridView с каждой строкой с указанием названия продукта, категории и цены вместе с флажком. Должно быть три кнопки: Установить все, Снять флажок все и Удалить выбранные продукты. При нажатии кнопки Проверить все флажки будут сняты, а сняты все флажки. При нажатии кнопки Удалить выбранные продукты отображается сообщение со списком ProductID значений выбранных продуктов, но не удаляет их.

Интерфейс из CheckBoxField.aspx перемещен в BatchDeleting.aspx

Рис. 3. Интерфейс из CheckBoxField.aspx был перемещен в BatchDeleting.aspx (щелкните для просмотра полноразмерного изображения)

Шаг 2. Удаление проверенных продуктов с помощью транзакций

После успешного копирования BatchDeleting.aspxинтерфейса пакетного удаления в остается только обновить код, чтобы кнопка Удалить выбранные продукты удаляла проверенные продукты с помощью DeleteProductsWithTransaction метода в ProductsBLL классе . Этот метод, добавленный в учебнике По изменению базы данных-оболочки в рамках транзакции, принимает в качестве входных данных List(Of T)ProductID значения и удаляет каждый из них ProductID в область транзакции.

Обработчик DeleteSelectedProducts событий Button Click в настоящее время использует следующий For Each цикл для перебора каждой строки GridView:

' Iterate through the Products.Rows property
For Each row As GridViewRow In Products.Rows
    ' Access the CheckBox
    Dim cb As CheckBox = row.FindControl("ProductSelector")
    If cb IsNot Nothing AndAlso cb.Checked Then
        ' Delete row! (Well, not really...)
        atLeastOneRowDeleted = True
        ' First, get the ProductID for the selected row
        Dim productID As Integer = _
            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 ...
        ' Dim productAPI As New ProductsBLL
        ' productAPI.DeleteProduct(productID)
        '............................................
    End If
Next

Для каждой ProductSelector строки на веб-элемент управления CheckBox ссылаются программными средствами. Если этот флажок установлен, строка ProductID s извлекается из DataKeys коллекции, а DeleteResults свойство Label s Text обновляется, включив в него сообщение о том, что строка была выбрана для удаления.

Приведенный выше код фактически не удаляет записи, так как вызов ProductsBLL метода класса закомментирован Delete . Если бы эта логика удаления применялась, код удалял бы продукты, но не в атомарной операции. То есть, если первые несколько удалений в последовательности завершилось успешно, а более поздний произошел сбой (возможно, из-за нарушения ограничения внешнего ключа), будет выдано исключение, но эти продукты, уже удаленные, останутся удаленными.

Чтобы обеспечить атомарность, необходимо вместо этого использовать ProductsBLL метод класса .DeleteProductsWithTransaction Так как этот метод принимает список значений ProductID , необходимо сначала скомпилировать этот список из сетки, а затем передать его в качестве параметра. Сначала мы создадим List(Of T) экземпляр типа Integer. В цикле For Each необходимо добавить выбранные значения продуктов ProductID в этот List(Of T)элемент . После цикла он List(Of T) должен быть передан методу ProductsBLL класса .DeleteProductsWithTransaction DeleteSelectedProducts Обновите обработчик событий Button Click следующим кодом:

Protected Sub DeleteSelectedProducts_Click(sender As Object, e As EventArgs) _
    Handles DeleteSelectedProducts.Click
    
    ' Create a List to hold the ProductID values to delete
    Dim productIDsToDelete As New System.Collections.Generic.List(Of Integer)
    ' Iterate through the Products.Rows property
    For Each row As GridViewRow In Products.Rows
        ' Access the CheckBox
        Dim cb As CheckBox = CType(row.FindControl("ProductSelector"), CheckBox)
        If cb IsNot Nothing AndAlso cb.Checked Then
            ' Save the ProductID value for deletion
            ' First, get the ProductID for the selected row
            Dim productID As Integer = _
                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)
        End If
    Next
    ' Call the DeleteProductsWithTransaction method and show the Label 
    ' if at least one row was deleted...
    If productIDsToDelete.Count > 0 Then
        Dim productAPI As New ProductsBLL()
        productAPI.DeleteProductsWithTransaction(productIDsToDelete)
        DeleteResults.Visible = True
        ' Rebind the data to the GridView
        Products.DataBind()
    End If
End Sub

Обновленный List(Of T) код создает объект типа Integer (productIDsToDelete) и заполняет его удаляемыми ProductID значениями. Если после цикла For Each выбран хотя бы один продукт, ProductsBLL вызывается метод класса DeleteProductsWithTransaction и передается этот список. Также DeleteResults отображается метка, и данные отскываются в GridView (чтобы только что удаленные записи больше не отображались в виде строк в сетке).

На рисунке 4 показан Элемент GridView после выбора ряда строк для удаления. На рисунке 5 показан экран сразу после нажатия кнопки Удалить выбранные продукты. Обратите внимание, что на рисунке 5 ProductID значения удаленных записей отображаются в метке под GridView, и эти строки больше не находятся в GridView.

Выбранные продукты будут удалены

Рис. 4. Выбранные продукты будут удалены (щелкните для просмотра полноразмерного изображения)

Значения Идентификатора продукта

Рис. 5. Значения удаленных продуктов ProductID перечислены под GridView (щелкните, чтобы просмотреть полноразмерное изображение)

Примечание

Чтобы проверить DeleteProductsWithTransaction атомарность метода, вручную добавьте запись для продукта в таблицу Order Details , а затем попытайтесь удалить этот продукт (вместе с другими). Вы получите нарушение ограничения внешнего ключа при попытке удалить продукт со связанным заказом, но обратите внимание, как выполняется откат других выбранных продуктов.

Сводка

Создание интерфейса пакетного удаления включает добавление GridView со столбцом флажков и веб-элемента управления "Кнопка", который при щелчке удаляет все выбранные строки в виде одной атомарной операции. В этом руководстве мы создали такой интерфейс, объединяя работу, выполненную в двух предыдущих руководствах: Добавление столбца GridView флажков и Упаковка изменений базы данных в транзакции. В первом руководстве мы создали GridView со столбцом флажков, а во втором мы реализовали метод в BLL, который при передаче List(Of T)ProductID значения удаляет их все в область транзакции.

В следующем руководстве мы создадим интерфейс для выполнения пакетной вставки.

Счастливое программирование!

Об авторе

Скотт Митчелл (Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с Веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часа. Его можно связать по адресу mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.

Отдельная благодарность

Эта серия учебников была проверена многими полезными рецензентами. Ведущие рецензенты этого руководства — Хилтон Гизеноу (Hilton Giesenow) и Тетера Мерфи (Teresa Murphy). Хотите ознакомиться с моими предстоящими статьями MSDN? Если да, опустите мне строку в mitchell@4GuysFromRolla.com.