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


Пакетное обновление (VB)

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

Скачать в формате PDF

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

Введение

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

В этом руководстве мы создадим GridView, где каждая строка редактируется (см. рис. 1). Так как каждая строка отрисовывается в интерфейсе редактирования, нет необходимости в столбце кнопок "Изменить", "Обновить" и "Отмена". Вместо этого на странице есть две кнопки "Обновить продукты", которые при щелчке перечисляют строки GridView и обновляют базу данных.

Каждая строка в GridView является редактируемой

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

Давайте приступим!

Примечание.

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

Изучение шагов по изменению всех строк GridView

Как описано в руководстве по вставке, обновлению и удалению данных , GridView предлагает встроенную поддержку редактирования базовых данных на основе строк. Внутри сетки GridView отмечает, какая строка редактируется через его EditIndex свойство. Так как GridView привязан к источнику данных, он проверяет каждую строку, чтобы узнать, равен ли индекс строки значению EditIndex. Если это так, поля строки отображаются с помощью интерфейсов редактирования. Для BoundFields интерфейс редактирования является TextBox, свойство которого Text присваивается значению поля данных, заданного свойством BoundField DataField . Для TemplateFields EditItemTemplate используется вместо ItemTemplate.

Помните, что рабочий процесс редактирования начинается, когда пользователь нажимает кнопку "Изменить строку". Это приводит к обратной обратной отправке, задает свойство GridView EditIndex индексу нажатой строки и повторно привязывает данные к сетке. При нажатии кнопки "Отмена строки" для обратной передачи EditIndex задано значение -1 перед повторной привязкой данных к сетке. Так как строки GridView начинают индексироваться с нуля, параметр EditIndex имеет -1 эффект отображения GridView в режиме только для чтения.

Свойство EditIndex хорошо подходит для редактирования строк, но не предназначено для пакетного редактирования. Чтобы сделать весь gridView редактируемым, необходимо иметь каждую строку отрисовки с помощью интерфейса редактирования. Самый простой способ сделать это — создать, где каждое редактируемое поле реализуется как TemplateField с его интерфейсом редактирования, определенным в .ItemTemplate

На следующих нескольких шагах мы создадим полностью редактируемый GridView. На шаге 1 мы создадим GridView и ObjectDataSource и преобразуем его BoundFields и CheckBoxField в TemplateFields. В шагах 2 и 3 мы переместим интерфейсы редактирования из шаблонных полей EditItemTemplate на их ItemTemplate .

Шаг 1. Отображение сведений о продукте

Прежде чем беспокоиться о создании GridView, где являются строки редактируемыми, давайте начнем с простого отображения сведений о продукте. BatchUpdate.aspx Откройте страницу в папке BatchData и перетащите GridView из панели элементов в конструктор. Задайте для GridView значение ID ProductsGrid и из смарт-тега выберите для привязки его к новому объекту ObjectDataSource с именем ProductsDataSource. Настройте ObjectDataSource для получения данных из ProductsBLL метода класса GetProducts .

Настройка ObjectDataSource для использования класса ProductsBLL

Рис. 2. Настройка ObjectDataSource для использования ProductsBLL класса (щелкните, чтобы просмотреть изображение полного размера)

Получение данных продукта с помощью метода GetProducts

Рис. 3. Получение данных продукта с помощью GetProducts метода (щелкните, чтобы просмотреть изображение полного размера)

Как и в GridView, функции изменения ObjectDataSource предназначены для работы на основе каждой строки. Чтобы обновить набор записей, необходимо написать немного кода в классе кода ASP.NET страницы, который пакетирует данные и передает его в BLL. Таким образом, задайте раскрывающийся список на вкладках UPDATE, INSERT и DELETE объекта ObjectDataSource значение (Нет). Чтобы завершить работу мастера, нажмите кнопку Готово .

Задайте раскрывающимся спискам в вкладках UPDATE, INSERT и DELETE (Нет)

Рис. 4. Задайте раскрывающийся список в вкладках UPDATE, INSERT и DELETE (Нет) (Щелкните, чтобы просмотреть изображение полного размера)

После завершения мастера настройки источника данных декларативная разметка ObjectDataSource должна выглядеть следующим образом:

<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>

Завершение работы мастера настройки источника данных также приводит к созданию BoundFields и CheckBoxField для полей данных продукта в GridView. В этом руководстве давайте разрешим пользователю просматривать и изменять имя продукта, категорию, цену и прекращенное состояние. Удалите все ProductNameCategoryNameполя и UnitPriceполя, а Discontinued также переименуйте HeaderText свойства первых трех полей в Product, Category и Price соответственно. Наконец, установите флажки "Включить разбиение по страницам" и "Включить сортировку" в смарт-теге GridView.

На этом этапе GridView имеет три BoundFields (ProductName, CategoryNameи UnitPrice) и CheckBoxField (Discontinued). Необходимо преобразовать эти четыре поля в TemplateFields, а затем переместить интерфейс редактирования из TemplateField s EditItemTemplate в его ItemTemplate.

Примечание.

Мы изучили создание и настройку TemplateFields в руководстве по настройке интерфейса изменения данных. Мы рассмотрим шаги по преобразованию BoundFields и CheckBoxField в TemplateFields и определению их интерфейсов редактирования в своих ItemTemplate s, но если вы застряли или нуждаетесь в обновлении, не стесняйтесь обращаться к этому предыдущему руководству.

В смарт-теге GridView щелкните ссылку "Изменить столбцы", чтобы открыть диалоговое окно "Поля". Затем выберите каждое поле и нажмите кнопку "Преобразовать это поле" в ссылку TemplateField.

Преобразование существующих boundFields и CheckBoxField в TemplateFields

Рис. 5. Преобразование существующих boundFields и CheckBoxField в TemplateFields

Теперь, когда каждое поле является templateField, мы готовы переместить интерфейс редактирования из EditItemTemplate s в ItemTemplate s.

Шаг 2. СозданиеProductName интерфейсовUnitPrice иDiscontinuedредактирование интерфейсов

ProductNameСоздание интерфейсов редактирования UnitPriceи Discontinued редактирования являются темой этого шага и довольно просто, так как каждый интерфейс уже определен в templateField sEditItemTemplate. CategoryName Создание интерфейса редактирования немного больше связано с тем, что нам нужно создать DropDownList применимых категорий. Этот CategoryName интерфейс редактирования решается на шаге 3.

Начнем с ProductName TemplateField. Щелкните ссылку "Изменить шаблоны" из смарт-тега GridView и выполните детализацию до ProductName шаблонаField EditItemTemplate. Выберите текстовое поле, скопируйте его в буфер обмена, а затем вставьте его в ProductName файл TemplateField s ItemTemplate. Измените свойство TextBox ID на ProductName.

Затем добавьте RequiredFieldValidator ItemTemplate в поле, чтобы убедиться, что пользователь предоставляет значение для каждого продукта. ControlToValidate Задайте для свойства значение ProductName, ErrorMessage для свойства необходимо указать имя продукта. Text и свойство *. После добавления этих дополнений ItemTemplateна экран должен выглядеть примерно так же, как на рис. 6.

ProductName TemplateField теперь включает текстовое поле и ОбязательныйFieldValidator

Рис. 6. ШаблонФилд ProductName теперь включает текстовое поле и ОбязательныйFieldValidator (щелкните, чтобы просмотреть изображение полного размера)

UnitPrice Для интерфейса редактирования начните с копирования Текстового поля из EditItemTemplate/>ItemTemplate. Затем поместите $ перед TextBox и задайте для свойства ID UnitPrice и его Columns свойства значение 8.

Кроме того, добавьте CompareValidator UnitPrice в s ItemTemplate , чтобы убедиться, что значение, введенное пользователем, является допустимым значением валюты больше или равно $0,00. Присвойте свойству проверяющего элемента ControlToValidate значение UnitPrice, его ErrorMessage свойству необходимо ввести допустимое значение валюты. Опустите любые символы валюты., его свойство *, Text его Type свойство to, его свойство Currencyto, и его Operator ValueToCompare свойство GreaterThanEqualдо 0.

Добавьте CompareValidator, чтобы убедиться, что введенная цена является неотрицательной денежной стоимостью

Рис. 7. Добавление compareValidator, чтобы убедиться, что введенная цена является неотрицательной денежной стоимостью (щелкните, чтобы просмотреть изображение полного размера)

Discontinued Для TemplateField можно использовать флажок, уже определенный в файле ItemTemplate. Просто задайте значение ID "Прекращено" и его Enabled свойство True.

Шаг 3. СозданиеCategoryNameинтерфейса редактирования

Интерфейс редактирования в CategoryName templateField содержит EditItemTemplate текстовое поле, отображающее значение CategoryName поля данных. Для этого нужно заменить раскрывающийся список возможных категорий.

Примечание.

Руководство по настройке интерфейса изменения данных содержит более тщательное и полное обсуждение настройки шаблона для включения dropDownList в отличие от текстового поля. Пока шаги здесь завершены, они представлены ужасно. Дополнительные сведения о создании и настройке категорий DropDownList см. в руководстве по настройке интерфейса изменения данных.

Перетащите раскрывающийся список из панели элементов в CategoryName шаблонФилд ItemTemplate, задав для нее значение ID Categories. На этом этапе мы обычно определим источник данных DropDownLists с помощью смарт-тега, создав объект ObjectDataSource. Однако это добавит ObjectDataSource в объект ItemTemplate, который приведет к экземпляру ObjectDataSource, созданному для каждой строки GridView. Вместо этого давайте создадим ОбъектDataSource за пределами TemplateFields GridView. Завершите редактирование шаблона и перетащите ОбъектDataSource из панели элементов в конструктор под ProductsDataSource ObjectDataSource. Назовите новый ObjectDataSource CategoriesDataSource и настройте его для использования CategoriesBLL метода класса GetCategories .

Настройка ObjectDataSource для использования класса CategoriesBLL

Рис. 8. Настройка ObjectDataSource для использования CategoriesBLL класса (щелкните, чтобы просмотреть изображение полного размера)

Получение данных категории с помощью метода GetCategories

Рис. 9. Получение данных категории с помощью GetCategories метода (щелкните, чтобы просмотреть изображение полного размера)

Так как этот ОбъектDataSource используется только для извлечения данных, задайте раскрывающийся список на вкладках UPDATE и DELETE (Нет). Чтобы завершить работу мастера, нажмите кнопку Готово .

Установите раскрывающийся список на вкладках UPDATE и DELETE (Нет)

Рис. 10. Установите раскрывающийся список на вкладках UPDATE и DELETE (Нет) (Щелкните, чтобы просмотреть изображение полного размера)

После завершения работы мастера CategoriesDataSource декларативная разметка должна выглядеть следующим образом:

<asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

CategoriesDataSource После создания и настройки вернитесь к CategoryName шаблону TemplateField ItemTemplate и в смарт-теге DropDownList щелкните ссылку "Выбор источника данных". В мастере настройки источника данных выберите CategoriesDataSource параметр из первого раскрывающегося списка и выберите CategoryName для отображения и CategoryID в качестве значения.

Привязка раскрывающегося списка к CategoriesDataSource

Рис. 11. Привязка раскрывающегося списка к CategoriesDataSource списку (щелкните, чтобы просмотреть изображение полного размера)

На этом этапе Categories в раскрывающемся списке перечислены все категории, но она пока не выбирает соответствующую категорию для продукта, привязанного к строке GridView. Для этого необходимо задать значение Categories DropDownList в SelectedValue CategoryID значении продукта. Щелкните ссылку "Изменить DataBindings" из смарт-тега DropDownList и свяжите SelectedValue свойство с полем CategoryID данных, как показано на рис. 12.

Привязка значения Идентификатора категории продукта к свойству SelectedValue DropDownList

Рис. 12. Привязка значения продукта CategoryID к свойству DropDownList SelectedValue

Одна из последних проблем остается: если продукт не имеет указанного CategoryID значения, то оператор SelectedValue привязки данных приведет к исключению. Это связано с тем, что DropDownList содержит только элементы для категорий и не предлагает вариант для тех продуктов, для которых задано NULL значение CategoryIDбазы данных. Чтобы устранить эту проблему, задайте свойство True DropDownList и добавьте новый элемент в DropDownListAppendDataBoundItems, опустив Value свойство из декларативного синтаксиса. То есть убедитесь, что Categories декларативный синтаксис DropDownList выглядит следующим образом:

<asp:DropDownList ID="Categories" runat="server" AppendDataBoundItems="True" 
    DataSourceID="CategoriesDataSource" DataTextField="CategoryName" 
    DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'>
    <asp:ListItem Value=">-- Select One --</asp:ListItem>
</asp:DropDownList>

Обратите внимание, что атрибут <asp:ListItem Value=""> select One Value явно задается пустой строкой. Вернитесь к руководству по настройке интерфейса изменения данных, чтобы более подробно обсудить, почему этот дополнительный элемент DropDownList необходим для обработки NULL дела и почему назначение Value свойства пустой строке является важным.

Примечание.

Здесь существует потенциальная проблема с производительностью и масштабируемостью, которую стоит упомянуть. Так как каждая строка имеет DropDownList, использующего CategoriesDataSource его источник данных, метод класса GetCategories будет вызываться n раз на посещение страницыCategoriesBLL, где n — количество строк в GridView. Эти вызовы n приводят к выполнению GetCategories n-запросов к базе данных. Это влияние на базу данных может уменьшиться путем кэширования возвращаемых категорий в кэше каждого запроса или на уровне кэширования с помощью зависимостей кэширования SQL или очень короткого срока действия на основе времени.

Шаг 4. Завершение интерфейса редактирования

Мы внесли ряд изменений в шаблоны GridView без приостановки просмотра хода выполнения. Ознакомьтесь с нашим прогрессом в браузере. Как показано на рисунке 13, каждая строка отрисовывается с помощью своего ItemTemplateинтерфейса редактирования ячейки.

Каждая строка GridView редактируется

Рис. 13. Каждая строка GridView редактируется (щелкните, чтобы просмотреть изображение полного размера)

На этом этапе мы должны заботиться о нескольких незначительных проблемах форматирования. Во-первых, обратите внимание, что UnitPrice значение содержит четыре десятичных знака. Чтобы устранить эту проблему, вернитесь к UnitPrice шаблону и ItemTemplate из смарт-тега TextBox щелкните ссылку "Изменить DataBindings". Затем укажите, что Text свойство должно быть отформатировано как число.

Форматирование текстового свойства в виде числа

Рис. 14. Форматирование Text свойства в виде числа

Во-вторых, разместим флажок в Discontinued столбце (вместо выравнивания по левому краю). Щелкните "Изменить столбцы" в смарт-теге GridView и выберите Discontinued TemplateField из списка полей в левом нижнем углу. ItemStyle Детализация и установка HorizontalAlign свойства в Центр, как показано на рис. 15.

Центр снятого флажка

Рис. 15. Центр Discontinued флажка

Затем добавьте элемент управления ValidationSummary на страницу и задайте для его ShowMessageBox свойства True значение и его ShowSummary свойство False. Кроме того, добавьте веб-элементы управления button, которые при нажатии будут обновлять изменения пользователя. В частности, добавьте два веб-элемента управления Button, один над GridView и один под ним, задав оба свойства элементов управления Text для update Products.

Так как интерфейс редактирования GridView определен в его TemplateFields ItemTemplate , EditItemTemplate они являются лишними и могут быть удалены.

После внесения указанных выше изменений форматирования, добавления элементов управления Button и удаления ненужных EditItemTemplate элементов синтаксис страницы должен выглядеть следующим образом:

<p>
    <asp:Button ID="UpdateAllProducts1" runat="server" Text="Update Products" />
</p>
<p>
    <asp:GridView ID="ProductsGrid" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
        AllowPaging="True" AllowSorting="True">
        <Columns>
            <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
                <ItemTemplate>
                    <asp:TextBox ID="ProductName" runat="server" 
                        Text='<%# Bind("ProductName") %>'></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
                        ControlToValidate="ProductName"
                        ErrorMessage="You must provide the product's name." 
                        runat="server">*</asp:RequiredFieldValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Category" 
                SortExpression="CategoryName">
                <ItemTemplate>
                    <asp:DropDownList ID="Categories" runat="server" 
                        AppendDataBoundItems="True" 
                        DataSourceID="CategoriesDataSource"
                        DataTextField="CategoryName" 
                        DataValueField="CategoryID" 
                        SelectedValue='<%# Bind("CategoryID") %>'>
                        <asp:ListItem>-- Select One --</asp:ListItem>
                    </asp:DropDownList>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Price" 
                SortExpression="UnitPrice">
                <ItemTemplate>
                    $<asp:TextBox ID="UnitPrice" runat="server" Columns="8" 
                        Text='<%# Bind("UnitPrice", "{0:N}") %>'></asp:TextBox>
                    <asp:CompareValidator ID="CompareValidator1" runat="server" 
                        ControlToValidate="UnitPrice"
                        ErrorMessage="You must enter a valid currency value. 
                                      Please omit any currency symbols."
                        Operator="GreaterThanEqual" Type="Currency" 
                        ValueToCompare="0">*</asp:CompareValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
                <ItemTemplate>
                    <asp:CheckBox ID="Discontinued" runat="server" 
                        Checked='<%# Bind("Discontinued") %>' />
                </ItemTemplate>
                <ItemStyle HorizontalAlign="Center" />
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</p>
<p>
    <asp:Button ID="UpdateAllProducts2" runat="server" Text="Update Products" />
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetProducts" TypeName="ProductsBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetCategories" TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" 
        ShowMessageBox="True" ShowSummary="False" />
</p>

На рисунке 16 показана эта страница при просмотре через браузер после добавления веб-элементов управления button и внесенных изменений форматирования.

Страница теперь включает две кнопки обновления продуктов

Рис. 16. Страница теперь включает две кнопки обновления продуктов (щелкните, чтобы просмотреть изображение полного размера)

Шаг 5. Обновление продуктов

Когда пользователь посещает эту страницу, он будет вносить изменения и нажимать одну из двух кнопок "Обновить продукты". На этом этапе необходимо как-то сохранить введенные пользователем значения для каждой ProductsDataTable строки в экземпляр, а затем передать его в метод BLL, который затем передает этот ProductsDataTable экземпляр методу DAL UpdateWithTransaction . Метод UpdateWithTransaction , созданный в предыдущем руководстве, гарантирует, что пакет изменений будет обновлен как атомарная операция.

Создайте метод с именем BatchUpdate и BatchUpdate.aspx.vb добавьте следующий код:

Private Sub BatchUpdate()
    ' Enumerate the GridView's Rows collection and create a ProductRow
    Dim productsAPI As New ProductsBLL()
    Dim products As Northwind.ProductsDataTable = productsAPI.GetProducts()
    For Each gvRow As GridViewRow In ProductsGrid.Rows
        ' Find the ProductsRow instance in products that maps to gvRow
        Dim productID As Integer = _
            Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
        Dim product As Northwind.ProductsRow = products.FindByProductID(productID)
        If product IsNot Nothing Then
            ' Programmatically access the form field elements in the 
            ' current GridViewRow
            Dim productName As TextBox = _
                CType(gvRow.FindControl("ProductName"), TextBox)
            Dim categories As DropDownList = _
                CType(gvRow.FindControl("Categories"), DropDownList)
            Dim unitPrice As TextBox = _
                CType(gvRow.FindControl("UnitPrice"), TextBox)
            Dim discontinued As CheckBox = _
                CType(gvRow.FindControl("Discontinued"), CheckBox)
            ' Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim()
            If categories.SelectedIndex = 0 Then 
                product.SetCategoryIDNull() 
            Else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue)
            End If
            If unitPrice.Text.Trim().Length = 0 Then 
                product.SetUnitPriceNull() 
            Else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
            End If
            product.Discontinued = discontinued.Checked
        End If
    Next
    ' Now have the BLL update the products data using a transaction
    productsAPI.UpdateWithTransaction(products)
End Sub

Этот метод начинается с получения всех продуктов обратно в ProductsDataTable методе BLL GetProducts . Затем он перечисляет коллекцию ProductGridGridViewRows. Коллекция Rows содержит экземпляр для каждой GridViewRow строки, отображаемой в GridView. Так как мы отображаем не более десяти строк на страницу, коллекция GridView Rows будет иметь не более десяти элементов.

Для каждой строкиProductID, полученной DataKeys из коллекции, выбран ProductsDataTableсоответствующий ProductsRow параметр. Четыре элемента управления входных данных TemplateField программно ссылаются и их значения, назначенные свойствам экземпляра ProductsRow . После того как значения строк GridView были использованы для обновления ProductsDataTable, он передается методу BLL UpdateWithTransaction , который, как мы видели в предыдущем руководстве, просто вызывается в метод DAL UpdateWithTransaction .

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

Примечание.

При привязке источника данных к GridView с помощью смарт-тега Visual Studio автоматически назначает значения первичного ключа источника данных свойству GridView DataKeyNames . Если объект ObjectDataSource не привязывается к GridView с помощью смарт-тега GridView, как описано на шаге 1, необходимо вручную задать для свойства GridView DataKeyNames значение ProductID, чтобы получить доступ к ProductID значению каждой строки через DataKeys коллекцию.

Код, используемый в BatchUpdate методах BLL, аналогичен тому, что в UpdateProduct методах BLL UpdateProduct извлекается только один ProductRow экземпляр. Код, назначающий свойства этого ProductRow объекта, совпадает с UpdateProducts методами и кодом в цикле For Each BatchUpdate, как и общий шаблон.

Чтобы завершить работу с этим руководством, необходимо вызвать BatchUpdate метод при нажатии любой из кнопок Update Products. Создайте обработчики событий для Click этих двух элементов управления Button и добавьте следующий код в обработчики событий:

BatchUpdate()
ClientScript.RegisterStartupScript(Me.GetType(), "message", _
    "alert('The products have been updated.');", True)

Сначала вызов выполняется BatchUpdate. ClientScript Затем свойство используется для внедрения JavaScript, в котором будет отображаться сообщение, которое считывает продукты, были обновлены.

Минуту, чтобы проверить этот код. Посетите BatchUpdate.aspx браузер, измените ряд строк и нажмите одну из кнопок "Обновить продукты". Если ошибки проверки входных данных отсутствуют, вы увидите сообщение, которое считывает обновленные продукты. Чтобы проверить атомарность обновления, попробуйте добавить случайное CHECK ограничение, например UnitPrice значение 1234,56. BatchUpdate.aspxЗатем отредактируйте ряд записей, убедившись, что одно из значений продукта UnitPrice имеет запрещенное значение (1234,56). Это приведет к ошибке при нажатии кнопки "Обновить продукты" с другими изменениями во время пакетной операции отката к исходным значениям.

АльтернативныйBatchUpdateметод

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

Для таких типов ситуаций рекомендуется использовать следующий BatchUpdateAlternate метод:

Private Sub BatchUpdateAlternate()
    ' Enumerate the GridView's Rows collection and create a ProductRow
    Dim productsAPI As New ProductsBLL()
    Dim products As New Northwind.ProductsDataTable()
    For Each gvRow As GridViewRow In ProductsGrid.Rows
        ' Create a new ProductRow instance
        Dim productID As Integer = _
            Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
        Dim currentProductDataTable As Northwind.ProductsDataTable = _
            productsAPI.GetProductByProductID(productID)
        If currentProductDataTable.Rows.Count > 0 Then
            Dim product As Northwind.ProductsRow = currentProductDataTable(0)
            Dim productName As TextBox = _
                CType(gvRow.FindControl("ProductName"), TextBox)
            Dim categories As DropDownList = _
                CType(gvRow.FindControl("Categories"), DropDownList)
            Dim unitPrice As TextBox = _
                CType(gvRow.FindControl("UnitPrice"), TextBox)
            Dim discontinued As CheckBox = _
                CType(gvRow.FindControl("Discontinued"), CheckBox)
            ' Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim()
            If categories.SelectedIndex = 0 Then 
                product.SetCategoryIDNull() 
            Else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue)
            End If
            If unitPrice.Text.Trim().Length = 0 Then 
                product.SetUnitPriceNull() 
            Else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
            End If
            product.Discontinued = discontinued.Checked
            ' Import the ProductRow into the products DataTable
            products.ImportRow(product)
        End If
    Next
    ' Now have the BLL update the products data using a transaction
    productsAPI.UpdateProductsWithTransaction(products)
End Sub

BatchMethodAlternate запускается путем создания пустого ProductsDataTable имени products. Затем он выполняет шаги по коллекции GridView Rows и для каждой строки получает определенную информацию о продукте с помощью метода BLL GetProductByProductID(productID) . Полученный ProductsRow экземпляр имеет свои свойства, обновленные таким же образом, как BatchUpdateи после обновления строки, импортируемой в products ProductsDataTable метод DataTableImportRow(DataRow).

После завершения products цикла содержит один ProductsRow экземпляр для каждой For Each строки в GridView. Так как каждый ProductsRow из экземпляров был добавлен products в (вместо обновления), если мы слепо передаем его UpdateWithTransaction методу, ProductsTableAdapter то попытается вставить каждую из записей в базу данных. Вместо этого необходимо указать, что каждая из этих строк была изменена (не добавлена).

Это можно сделать, добавив новый метод в BLL с именем UpdateProductsWithTransaction. UpdateProductsWithTransaction, как показано ниже, задает каждый из ProductsRow экземпляров в списке ProductsDataTable Modified, а затем передает ProductsDataTable метод DALUpdateWithTransaction.RowState

Public Function UpdateProductsWithTransaction _
    (ByVal products As Northwind.ProductsDataTable) As Integer
    ' Mark each product as Modified
    products.AcceptChanges()
    For Each product As Northwind.ProductsRow In products
        product.SetModified()
    Next
    ' Update the data via a transaction
    Return UpdateWithTransaction(products)
End Function

Итоги

GridView предоставляет встроенные возможности редактирования строк, но не поддерживает создание полностью редактируемых интерфейсов. Как мы видели в этом руководстве, такие интерфейсы возможны, но требуют немного работы. Чтобы создать GridView, где каждая строка редактируется, необходимо преобразовать поля GridView в TemplateFields и определить интерфейс редактирования в пределах ItemTemplate S. Кроме того, необходимо добавить на страницу веб-элементы управления "Все кнопки типа" отдельно от GridView. Эти обработчики событий Button Click должны перечислить коллекцию GridView Rows , сохранить изменения в объекте ProductsDataTableи передать обновленные сведения в соответствующий метод BLL.

В следующем руководстве мы посмотрим, как создать интерфейс для удаления пакетной службы. В частности, каждая строка GridView будет включать флажок и вместо кнопок "Обновить все тип", у нас будут кнопки "Удалить выбранные строки".

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

Об авторе

Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Сэмс Учит себя ASP.NET 2.0 в 24 часах. Он может быть достигнут в mitchell@4GuysFromRolla.com. или через его блог, который можно найти на http://ScottOnWriting.NET.

Особое спасибо

Эта серия учебников была проверена многими полезными рецензентами. Ведущие рецензенты для этого руководства были Тереса Мерфи и Дэвид Суру. Хотите просмотреть мои предстоящие статьи MSDN? Если да, упадите меня линию в mitchell@4GuysFromRolla.com.