Перенос изменений базы данных в транзакции (VB)Wrapping Database Modifications within a Transaction (VB)

по Скотт Митчеллby Scott Mitchell

Скачать код или скачать PDFDownload Code or Download PDF

Этот учебник является первым из четырех, в котором рассматривается обновление, удаление и вставка пакетов данных.This tutorial is the first of four that looks at updating, deleting, and inserting batches of data. В этом учебнике мы рассмотрим, как транзакции базы данных позволяют выполнять пакетные изменения в рамках атомарной операции, что гарантирует успешное завершение всех шагов или выполнение всех шагов.In this tutorial we learn how database transactions allow batch modifications to be carried out as an atomic operation, which ensures that either all steps succeed or all steps fail.

ВведениеIntroduction

Как мы видели в обзоре руководства по вставке, обновлению и удалению данных , GridView предоставляет встроенную поддержку редактирования и удаления на уровне строк.As we saw starting with the An Overview of Inserting, Updating, and Deleting Data tutorial, the GridView provides built-in support for row-level editing and deleting. С помощью нескольких щелчков мыши можно создать обширный интерфейс изменения данных без написания строки кода, если вы используете редактирование и удаление для отдельных строк.With a few clicks of the mouse it is possible to create a rich data modification interface without writing a line of code, so long as you are content with editing and deleting on a per-row basis. Однако в некоторых сценариях это недостаточно, и необходимо предоставить пользователям возможность изменять или удалять пакет записей.However, in certain scenarios this is insufficient and we need to provide users with the ability to edit or delete a batch of records.

Например, большинство веб-клиентов электронной почты используют сетку для перечисления каждого сообщения, где каждая строка содержит флажок вместе с информацией электронной почты (тема, отправитель и т. д.).For example, most web-based email clients use a grid to list each message where each row includes a checkbox along with the email s information (subject, sender, and so forth). Этот интерфейс позволяет пользователю удалить несколько сообщений, установив их, а затем нажав кнопку Удалить выбранные сообщения.This interface permits the user to delete multiple messages by checking them and then clicking a Delete Selected Messages button. Интерфейс редактирования пакетной службы идеально подходит в ситуациях, когда пользователи часто редактируют множество различных записей.A batch editing interface is ideal in situations where users commonly edit many different records. Вместо того чтобы принудительно изменять пользователь, внести изменения, а затем нажать кнопку Обновить для каждой записи, которую необходимо изменить, интерфейс редактирования пакетной службы отображает каждую строку с помощью интерфейса правки.Rather than forcing the user to click Edit, make their change, and then click Update for each record that needs to be modified, a batch editing interface renders each row with its editing interface. Пользователь может быстро изменить набор строк, которые необходимо изменить, а затем сохранить эти изменения, нажав кнопку Обновить все.The user can quickly modify the set of rows that need to be changed and then save these changes by clicking an Update All button. В этом наборе руководств мы рассмотрим создание интерфейсов для вставки, изменения и удаления пакетов данных.In this set of tutorials we'll examine how to create interfaces for inserting, editing, and deleting batches of data.

При выполнении пакетных операций важно определить, возможно ли успешное выполнение некоторых операций в пакете, в то время как другие завершаются сбоем.When performing batch operations it s important to determine whether it should be possible for some of the operations in the batch to succeed while others fail. Рассмотрим пакетное удаление интерфейса. что должно произойти, если первая выбранная запись успешно удалена, а вторая — нет, скажем, из-за нарушения ограничения внешнего ключа?Consider a batch deleting interface - what should happen if the first selected record is deleted successfully, but the second one fails, say, because of a foreign key constraint violation? Следует ли выполнить откат первой записи, а также допустимость удаления первой записи?Should the first record s delete be rolled back or is it acceptable for the first record to remain deleted?

Если необходимо, чтобы Пакетная операция считалась атомарной операцией, в которой либо все шаги выполнены успешно, либо все шаги завершаются ошибкой, уровень доступа к данным должен быть дополнен к включению поддержки транзакций базы данных.If you want the batch operation to be treated as an atomic operation, one where either all of the steps succeed or all of the steps fail, then the Data Access Layer needs to be augmented to include support for database transactions. Транзакции базы данных гарантируют атомарность для набора инструкций INSERT, UPDATEи DELETE, выполняемых по отношению к транзакции, и являются функцией, поддерживаемой большинством современных систем баз данных.Database transactions guarantee atomicity for the set of INSERT, UPDATE, and DELETE statements executed under the umbrella of the transaction and are a feature supported by most all modern database systems.

В этом учебнике мы рассмотрим, как расширить DAL для использования транзакций базы данных.In this tutorial we'll look at how to extend the DAL to use database transactions. В последующих руководствах рассматривается реализация веб-страниц для пакетной вставки, обновления и удаления интерфейсов.Subsequent tutorials will examine implementing web pages for batch inserting, updating, and deleting interfaces. Давайте приступим к работе!Let s get started!

Note

При изменении данных в пакетной транзакции атомарность не всегда требуется.When modifying data in a batch transaction, atomicity is not always needed. В некоторых сценариях может быть приемлемым, что некоторые изменения данных будут успешными, и другие в том же пакете завершатся ошибкой, например при удалении набора сообщений электронной почты из Интернет-клиента.In some scenarios, it may be acceptable to have some data modifications succeed and others in the same batch fail, such as when deleting a set of emails from a web-based email client. Если в процессе удаления произошла ошибка базы данных, вероятно, это приемлемо, что записи, обработанные без ошибок, остаются неизменными.If there s a database error midway through the deletion process, it s probably acceptable that those records processed without error remain deleted. В таких случаях DAL не требуется изменять для поддержки транзакций базы данных.In such cases, the DAL does not need to be modified to support database transactions. Однако существуют и другие сценарии пакетной операции, где атомарность крайне важна.There are other batch operation scenarios, however, where atomicity is vital. Когда клиент перемещает свои фонды с одного банковского счета на другой, необходимо выполнить две операции: фонды должны вычитаться из первой учетной записи, а затем добавляться во вторую.When a customer moves her funds from one bank account to another, two operations must be performed: the funds must be deducted from the first account and then added to the second. В то время как банк может не забывать о том, что первый этап выполнен успешно, но второй шаг не пройден, его клиенты хорошо обеспокоен.While the bank may not mind having the first step succeed but the second step fail, its customers would understandably be upset. Я рекомендую работать с этим руководством и реализовать усовершенствования DAL для поддержки транзакций базы данных, даже если вы не планируете использовать их в пакетной службе вставки, обновления и удаления, которые будут создаваться в следующих трех руководствах.I encourage you to work through this tutorial and implement the enhancements to the DAL to support database transactions even if you do not plan on using them in the batch inserting, updating, and deleting interfaces we'll be building in the following three tutorials.

Общие сведения о транзакцияхAn Overview of Transactions

В большинстве баз данных предусмотрена поддержка транзакций, что позволяет объединять несколько команд базы данных в одну логическую единицу работы.Most databases include support for transactions, which enable multiple database commands to be grouped into a single logical unit of work. Команды базы данных, составляющие транзакцию, гарантированно будут атомарными, то есть все команды завершатся сбоем или будут успешными.The database commands that comprise a transaction are guaranteed to be atomic, meaning that either all commands will fail or all will succeed.

Как правило, транзакции реализуются с помощью инструкций SQL в следующем шаблоне:In general, transactions are implemented through SQL statements using the following pattern:

  1. Указывает на начало транзакции.Indicate the start of a transaction.
  2. Выполните инструкции SQL, составляющие транзакцию.Execute the SQL statements that comprise the transaction.
  3. При возникновении ошибки в одной из инструкций, выполненных на шаге 2, необходимо выполнить откат транзакции.If there is an error in one of the statements from Step 2, rollback the transaction.
  4. Если все инструкции, выполненные на шаге 2, завершаются без ошибок, зафиксируйте транзакцию.If all of the statements from Step 2 complete without error, commit the transaction.

Инструкции SQL, используемые для создания, фиксации и отката транзакции, можно указать вручную при написании скриптов SQL или при создании хранимых процедур или с помощью программных средств, используя ADO.NET или классы в пространстве именSystem.Transactions.The SQL statements used to create, commit, and roll back the transaction can be entered manually when writing SQL scripts or creating stored procedures, or through programmatic means using either ADO.NET or the classes in the System.Transactions namespace. В этом учебнике мы будем анализировать только управление транзакциями с помощью ADO.NET.In this tutorial we will only examine managing transactions using ADO.NET. В следующем учебном курсе мы рассмотрим, как использовать хранимые процедуры на уровне доступа к данным, после чего будут рассмотрены инструкции SQL для создания, отката и фиксации транзакций.In a future tutorial we will look at how to use stored procedures in the Data Access Layer, at which time we'll explore the SQL statements for creating, rolling back, and committing transactions. В то же время изучите Управление транзакциями в SQL Server хранимых процедурах для получения дополнительных сведений.In the meantime, consult Managing Transactions in SQL Server Stored Procedures for more information.

Note

КлассTransactionScope в пространстве имен System.Transactions позволяет разработчикам программно переносить ряд инструкций в области транзакции и включает поддержку сложных транзакций, включающих несколько источников, таких как базы данных и даже разнородные типы хранилищ данных, такие как Microsoft SQL Server база, база данных Oracle и веб-служба.The TransactionScope class in the System.Transactions namespace enables developers to programmatically wrap a series of statements within the scope of a transaction and includes support for complex transactions that involve multiple sources, such as two different databases or even heterogeneous types of data stores, such as a Microsoft SQL Server database, an Oracle database, and a Web service. Я решил использовать ADO.NET транзакции для работы с этим руководством, а не класс TransactionScope, так как ADO.NET более специфичен для транзакций базы данных и, во многих случаях, намного менее интенсивно использует ресурсы.I ve decided to use ADO.NET transactions for this tutorial instead of the TransactionScope class because ADO.NET is more specific for database transactions and, in many cases, is far less resource intensive. Кроме того, в некоторых сценариях TransactionScope класс использует координатор распределенных транзакций Майкрософт (MSDTC).In addition, under certain scenarios the TransactionScope class uses the Microsoft Distributed Transaction Coordinator (MSDTC). Проблемы с конфигурацией, реализацией и производительностью, связанные с MSDTC, делают его довольно специализированным и дополнительным разделом, кроме области действия этих учебников.The configuration, implementation, and performance issues surrounding MSDTC makes it a rather specialized and advanced topic and beyond the scope of these tutorials.

При работе с поставщиком SqlClient в ADO.NET транзакции инициируются посредством вызова методаBeginTransaction классаSqlConnection , который возвращает объектSqlTransaction.When working with the SqlClient provider in ADO.NET, transactions are initiated through a call to the SqlConnection class s BeginTransaction method, which returns a SqlTransaction object. Инструкции изменения данных, описывающего транзакцию, помещаются в блок try...catch.The data modification statements that makeup the transaction are placed within a try...catch block. Если ошибка возникает в инструкции в блоке try, выполнение передается в блок catch, где можно выполнить откат транзакции с помощью методаRollbackSqlTransaction Object s.If an error occurs in a statement in the try block, execution transfers to the catch block where the transaction can be rolled back via the SqlTransaction object s Rollback method. Если все инструкции успешно завершены, вызов метода SqlTransaction Object s Commit в конце блока try фиксирует транзакцию.If all of the statements complete successfully, a call to the SqlTransaction object s Commit method at the end of the try block commits the transaction. Этот шаблон показан в следующем фрагменте кода.The following code snippet illustrates this pattern. Дополнительные сведения о синтаксисе и примеры использования транзакций с ADO.NET см. в разделе поддержание согласованности базы данных с транзакциями .See Maintaining Database Consistency with Transactions for additional syntax and examples of using transactions with ADO.NET.

' Create the SqlTransaction object
Dim myTransaction As SqlTransaction = SqlConnectionObject.BeginTransaction();
Try
    '
    ' ... Perform the database transaction�s data modification statements...
    '
    ' If we reach here, no errors, so commit the transaction
    myTransaction.Commit()
Catch
    ' If we reach here, there was an error, so rollback the transaction
    myTransaction.Rollback()
    Throw
End Try

По умолчанию адаптеры таблиц в типизированном наборе данных не используют транзакции.By default, the TableAdapters in a Typed DataSet do not use transactions. Чтобы обеспечить поддержку транзакций, необходимо дополнить классы TableAdapter, чтобы включить дополнительные методы, использующие приведенный выше шаблон для выполнения ряда инструкций изменения данных в области транзакции.To provide support for transactions we need to augment the TableAdapter classes to include additional methods that use the above pattern to perform a series of data modification statements within the scope of a transaction. На этапе 2 мы посмотрим, как использовать разделяемые классы для добавления этих методов.In Step 2 we'll see how to use partial classes to add these methods.

Шаг 1. Создание работы с пакетными веб-страницами данныхStep 1: Creating the Working with Batched Data Web Pages

Прежде чем приступить к изучению способов расширения DAL для поддержки транзакций базы данных, давайте сначала создадим веб-страницы ASP.NET, которые понадобятся для работы с этим руководством, и три следующих.Before we start exploring how to augment the DAL to support database transactions, let s first take a moment to create the ASP.NET web pages that we will need for this tutorial and the three that follow. Начните с добавления новой папки с именем BatchData, а затем добавьте следующие страницы ASP.NET, связав каждую страницу с главной страницей Site.master.Start by adding a new folder named BatchData and then add the following ASP.NET pages, associating each page with the Site.master master page.

  • Default.aspx
  • Transactions.aspx
  • BatchUpdate.aspx
  • BatchDelete.aspx
  • BatchInsert.aspx

Добавление страниц ASP.NET для учебников, связанных с SqlDataSource

Рис. 1. добавление страниц ASP.NET для учебников, связанных с SqlDataSourceFigure 1: Add the ASP.NET Pages for the SqlDataSource-Related Tutorials

Как и в других папках, Default.aspx будет использовать пользовательский элемент управления SectionLevelTutorialListing.ascx для составления списка руководств в своем разделе.As with the other folders, Default.aspx will use the SectionLevelTutorialListing.ascx User Control to list the tutorials within its section. Таким образом, добавьте этот пользовательский элемент управления в Default.aspx, перетащив его из обозреватель решений на страницу s представление конструирования.Therefore, add this User Control to Default.aspx by dragging it from the Solution Explorer onto the page s Design view.

добавить пользовательский элемент управления SectionLevelTutorialListing. ascx в Default. aspxAdd the SectionLevelTutorialListing.ascx User Control to Default.aspx

Рис. 2. Добавление пользовательского элемента управления SectionLevelTutorialListing.ascx в Default.aspx (щелкните, чтобы просмотреть изображение с полным размером)Figure 2: Add the SectionLevelTutorialListing.ascx User Control to Default.aspx (Click to view full-size image)

Наконец, добавьте эти четыре страницы в качестве записей в файл Web.sitemap.Lastly, add these four pages as entries to the Web.sitemap file. В частности, добавьте следующую разметку после настройки схемы узла <siteMapNode>.Specifically, add the following markup after the Customizing the Site Map <siteMapNode>:

<siteMapNode title="Working with Batched Data" 
    url="~/BatchData/Default.aspx" 
    description="Learn how to perform batch operations as opposed to 
                 per-row operations.">
    
    <siteMapNode title="Adding Support for Transactions" 
        url="~/BatchData/Transactions.aspx" 
        description="See how to extend the Data Access Layer to support 
                     database transactions." />
    <siteMapNode title="Batch Updating" 
        url="~/BatchData/BatchUpdate.aspx" 
        description="Build a batch updating interface, where each row in a 
                      GridView is editable." />
    <siteMapNode title="Batch Deleting" 
        url="~/BatchData/BatchDelete.aspx" 
        description="Explore how to create an interface for batch deleting 
                     by adding a CheckBox to each GridView row." />
    <siteMapNode title="Batch Inserting" 
        url="~/BatchData/BatchInsert.aspx" 
        description="Examine the steps needed to create a batch inserting 
                     interface, where multiple records can be created at the 
                     click of a button." />
</siteMapNode>

После обновления Web.sitemapпросмотрите веб-сайт учебников в браузере.After updating Web.sitemap, take a moment to view the tutorials website through a browser. В меню слева теперь содержатся элементы для работы с учебниками по пакетным данным.The menu on the left now includes items for the working with batched data tutorials.

Схема узла теперь включает в себя записи для работы с пакетными учебниками по работе с данными

Рис. 3. схема узла теперь включает в себя записи для работы с пакетными учебниками по работе с даннымиFigure 3: The Site Map Now Includes Entries for the Working with Batched Data Tutorials

Шаг 2. обновление уровня доступа к данным для поддержки транзакций базы данныхStep 2: Updating the Data Access Layer to Support Database Transactions

Как мы обсуждали в первом учебном курсе, Создание уровня доступа к данным, типизированный набор данных в нашем DAL состоит из таблиц DataTable и TableAdapter.As we discussed back in the first tutorial, Creating a Data Access Layer, the Typed DataSet in our DAL is composed of DataTables and TableAdapters. Таблицы данных содержат данные, а адаптеры таблиц предоставляют функции для чтения данных из базы данных в таблицы DataTable, обновления базы данных с изменениями, внесенными в таблицы DataTable, и т. д.The DataTables hold data while the TableAdapters provide the functionality to read data from the database into the DataTables, to update the database with changes made to the DataTables, and so forth. Вспомним, что адаптеры таблиц предоставляют два шаблона для обновления данных, которые я называть пакетным обновлением и прямой базой данных.Recall that the TableAdapters provide two patterns for updating data, which I referred to as Batch Update and DB-Direct. При использовании шаблона обновления пакетной службы TableAdapter передается набор данных, DataTable или коллекция Rows.With the Batch Update pattern, the TableAdapter is passed a DataSet, DataTable, or collection of DataRows. Эти данные перечисляются и для каждой вставленной, измененной или удаленной строки выполняется InsertCommand, UpdateCommandили DeleteCommand.This data is enumerated and for each inserted, modified, or deleted row, the InsertCommand, UpdateCommand, or DeleteCommand is executed. При использовании непосредственного шаблона DB TableAdapter передает значения столбцов, необходимых для вставки, обновления или удаления одной записи.With the DB-Direct pattern, the TableAdapter is instead passed the values of the columns necessary for inserting, updating, or deleting a single record. Затем метод прямого шаблона базы данных использует переданные значения для выполнения соответствующего оператора InsertCommand, UpdateCommandили DeleteCommand.The DB Direct pattern method then uses those passed-in values to execute the appropriate InsertCommand, UpdateCommand, or DeleteCommand statement.

Независимо от используемого шаблона обновления, автоматически создаваемые методы TableAdapter не используют транзакции.Regardless of the update pattern used, the TableAdapters auto-generated methods do not use transactions. По умолчанию каждая операция вставки, обновления или удаления, выполняемая адаптером таблицы, обрабатывается как единое дискретное действие.By default each insert, update, or delete performed by the TableAdapter is treated as a single discrete operation. Например, представьте, что непосредственный шаблон DB используется в коде BLL для вставки десяти записей в базу данных.For instance, imagine that the DB-Direct pattern is used by some code in the BLL to insert ten records into the database. Этот код вызовет метод Insert TableAdapter 10 раз.This code would call the TableAdapter s Insert method ten times. Если первые пять вставок успешны, но шестой из них привела к исключению, первые пять вставленных записей останутся в базе данных.If the first five inserts succeed, but the sixth one resulted in an exception, the first five inserted records would remain in the database. Аналогично, если шаблон пакетного обновления используется для выполнения операций вставки, обновления и удаления для вставленных, измененных и удаленных строк в таблице данных DataTable, если первые несколько изменений были выполнены удачно, а в более поздней — произошла ошибка, эти предыдущие изменения завершено останется в базе данных.Similarly, if the Batch Update pattern is used to perform inserts, updates, and deletes to the inserted, modified, and deleted rows in a DataTable, if the first several modifications succeeded but a later one encountered an error, those earlier modifications that completed would remain in the database.

В некоторых сценариях мы хотим обеспечить атомарность в ряде изменений.In certain scenarios we want to ensure atomicity across a series of modifications. Для этого необходимо вручную расширить TableAdapter, добавив новые методы, которые выполняют InsertCommand, UpdateCommandи DeleteCommand s под символом-точкой транзакции.To accomplish this we must manually extend the TableAdapter by adding new methods that execute the InsertCommand, UpdateCommand, and DeleteCommand s under the umbrella of a transaction. При создании уровня доступа к данным мы рассматривали использование разделяемых классов для расширения функциональных возможностей DataTables в типизированном наборе данных.In Creating a Data Access Layer we looked at using partial classes to extend the functionality of the DataTables within the Typed DataSet. Этот метод также можно использовать с адаптерами таблиц.This technique can also be used with TableAdapters.

Типизированный набор данных Northwind.xsd расположен в папке App_Code Folders DAL.The Typed DataSet Northwind.xsd is located in the App_Code folder s DAL subfolder. Создайте вложенную папку в папке DAL с именем TransactionSupport и добавьте новый файл класса с именем ProductsTableAdapter.TransactionSupport.vb (см. рис. 4).Create a subfolder in the DAL folder named TransactionSupport and add a new class file named ProductsTableAdapter.TransactionSupport.vb (see Figure 4). Этот файл будет содержать частичную реализацию ProductsTableAdapter, включающую методы для выполнения изменений данных с помощью транзакции.This file will hold the partial implementation of the ProductsTableAdapter that includes methods for performing data modifications using a transaction.

Добавьте папку с именем Трансактионсуппорт и файл класса с именем Продуктстаблеадаптер. Трансактионсуппорт. vb.

Рис. 4. Добавление папки с именем TransactionSupport и файла класса с именем ProductsTableAdapter.TransactionSupport.vbFigure 4: Add a Folder Named TransactionSupport and a Class File Named ProductsTableAdapter.TransactionSupport.vb

Введите следующий код в файл ProductsTableAdapter.TransactionSupport.vb:Enter the following code into the ProductsTableAdapter.TransactionSupport.vb file:

Imports System.Data
Imports System.Data.SqlClient
Namespace NorthwindTableAdapters
    Partial Public Class ProductsTableAdapter
        Private _transaction As SqlTransaction
        Private Property Transaction() As SqlTransaction
            Get
                Return Me._transaction
            End Get
            Set(ByVal Value As SqlTransaction)
                Me._transaction = Value
            End Set
        End Property
        Public Sub BeginTransaction()
            ' Open the connection, if needed
            If Me.Connection.State <> ConnectionState.Open Then
                Me.Connection.Open()
            End If
            ' Create the transaction and assign it to the Transaction property
            Me.Transaction = Me.Connection.BeginTransaction()
            ' Attach the transaction to the Adapters
            For Each command As SqlCommand In Me.CommandCollection
                command.Transaction = Me.Transaction
            Next
            Me.Adapter.InsertCommand.Transaction = Me.Transaction
            Me.Adapter.UpdateCommand.Transaction = Me.Transaction
            Me.Adapter.DeleteCommand.Transaction = Me.Transaction
        End Sub
        Public Sub CommitTransaction()
            ' Commit the transaction
            Me.Transaction.Commit()
            ' Close the connection
            Me.Connection.Close()
        End Sub
        Public Sub RollbackTransaction()
            ' Rollback the transaction
            Me.Transaction.Rollback()
            ' Close the connection
            Me.Connection.Close()
        End Sub
    End Class
End Namespace

Ключевое слово Partial в объявлении класса указывает компилятору, что члены, добавленные в, должны быть добавлены в класс ProductsTableAdapter в пространстве имен NorthwindTableAdapters.The Partial keyword in the class declaration here indicates to the compiler that the members added within are to be added to the ProductsTableAdapter class in the NorthwindTableAdapters namespace. Обратите внимание на оператор Imports System.Data.SqlClient в верхней части файла.Note the Imports System.Data.SqlClient statement at the top of the file. Так как TableAdapter настроен для использования поставщика SqlClient, внутренне он использует объект SqlDataAdapter , чтобы выдать свои команды в базу данных.Since the TableAdapter was configured to use the SqlClient provider, internally it uses a SqlDataAdapter object to issue its commands to the database. Следовательно, необходимо использовать класс SqlTransaction, чтобы начать транзакцию, а затем зафиксировать ее или выполнить ее откат.Consequently, we need to use the SqlTransaction class to begin the transaction and then to commit it or roll it back. Если используется хранилище данных, отличное от Microsoft SQL Server, необходимо использовать соответствующий поставщик.If you are using a data store other than Microsoft SQL Server, you'll need to use the appropriate provider.

Эти методы предоставляют стандартные блоки, необходимые для запуска, отката и фиксации транзакции.These methods provide the building blocks needed to start, rollback, and commit a transaction. Они помечены Public, что позволяет использовать их из ProductsTableAdapter, из другого класса в DAL или из другого слоя в архитектуре, например BLL.They are marked Public, enabling them to be used from within the ProductsTableAdapter, from another class in the DAL, or from another layer in the architecture, such as the BLL. BeginTransaction открывает внутренние SqlConnection TableAdapter (при необходимости), начинает транзакцию и назначает ее свойству Transaction и присоединяет транзакцию к внутренним SqlCommand объектам SqlDataAdapter s.BeginTransaction opens the TableAdapter s internal SqlConnection (if needed), begins the transaction and assigns it to the Transaction property, and attaches the transaction to the internal SqlDataAdapter s SqlCommand objects. Прежде чем закрывать внутренний объект Rollback, CommitTransaction и RollbackTransaction вызывают Transaction объектов Commit и Connection соответственно.CommitTransaction and RollbackTransaction call the Transaction object s Commit and Rollback methods, respectively, before closing the internal Connection object.

Шаг 3. Добавление методов для обновления и удаления данных по символу-отчасти транзакцииStep 3: Adding Methods to Update and Delete Data Under the Umbrella of a Transaction

После выполнения этих методов мы повторно готовы к добавлению методов к ProductsDataTable или BLL, выполняющему ряд команд под символом-отработкой транзакции.With these methods complete, we re ready to add methods to ProductsDataTable or the BLL that perform a series of commands under the umbrella of a transaction. Следующий метод использует шаблон пакетного обновления для обновления ProductsDataTable экземпляра с помощью транзакции.The following method uses the Batch Update pattern to update a ProductsDataTable instance using a transaction. Он запускает транзакцию, вызывая метод BeginTransaction, а затем использует блок Try...Catch для выполнения инструкций изменения данных.It starts a transaction by calling the BeginTransaction method and then uses a Try...Catch block to issue the data modification statements. Если вызов метода Update Adapter Objects приводит к возникновению исключения, выполнение передается в блок catch, где будет выполнен откат транзакции, а исключение повторно выбрасывается.If the call to the Adapter object s Update method results in an exception, execution will transfer to the catch block where the transaction will be rolled back and the exception re-thrown. Помните, что метод Update реализует шаблон пакетного обновления, перечисляя строки предоставленного ProductsDataTable и выполняя необходимые InsertCommand, UpdateCommandи DeleteCommand s.Recall that the Update method implements the Batch Update pattern by enumerating the rows of the supplied ProductsDataTable and performing the necessary InsertCommand, UpdateCommand, and DeleteCommand s. Если какая-либо из этих команд приводит к ошибке, выполняется откат транзакции с отменой предыдущих изменений, внесенных в течение времени существования транзакции.If any one of these commands results in an error, the transaction is rolled back, undoing the previous modifications made during the transaction s lifetime. Если инструкция Update завершена без ошибок, транзакция фиксируется полностью.Should the Update statement complete without error, the transaction is committed in its entirety.

Public Function UpdateWithTransaction _
    (ByVal dataTable As Northwind.ProductsDataTable) As Integer
    
    Me.BeginTransaction()
    Try
        ' Perform the update on the DataTable
        Dim returnValue As Integer = Me.Adapter.Update(dataTable)
        ' If we reach here, no errors, so commit the transaction
        Me.CommitTransaction()
        Return returnValue
    Catch
        ' If we reach here, there was an error, so rollback the transaction
        Me.RollbackTransaction()
        Throw
    End Try
End Function

Добавьте метод UpdateWithTransaction в класс ProductsTableAdapter с помощью разделяемого класса в ProductsTableAdapter.TransactionSupport.vb.Add the UpdateWithTransaction method to the ProductsTableAdapter class through the partial class in ProductsTableAdapter.TransactionSupport.vb. Кроме того, этот метод можно добавить в класс ProductsBLL уровня бизнес-логики с небольшими синтаксическими изменениями.Alternatively, this method could be added to the Business Logic Layer s ProductsBLL class with a few minor syntactical changes. А именно, ключевое слово Me в Me.BeginTransaction(), Me.CommitTransaction()и Me.RollbackTransaction() необходимо заменить на Adapter (Помните, что Adapter — это имя свойства в ProductsBLL типа ProductsTableAdapter).Namely, the keyword Me in Me.BeginTransaction(), Me.CommitTransaction(), and Me.RollbackTransaction() would need to be replaced with Adapter (recall that Adapter is the name of a property in ProductsBLL of type ProductsTableAdapter).

В методе UpdateWithTransaction используется шаблон пакетного обновления, но в области транзакции можно также использовать ряд прямых вызовов DB, как показано в следующем методе.The UpdateWithTransaction method uses the Batch Update pattern, but a series of DB-Direct calls can also be used within the scope of a transaction, as the following method shows. Метод DeleteProductsWithTransaction принимает в качестве входных данных List(Of T) типа Integer, который ProductID для удаления.The DeleteProductsWithTransaction method accepts as input a List(Of T) of type Integer, which are the ProductID s to delete. Метод инициирует транзакцию с помощью вызова BeginTransaction, а затем в блоке Try проходит по переданному списку, вызывая метод Delete прямого шаблона DB для каждого значения ProductID.The method initiates the transaction via a call to BeginTransaction and then, in the Try block, iterates through the supplied list calling the DB-Direct pattern Delete method for each ProductID value. При сбое любого вызова Delete управление передается блоку Catch, в котором выполняется откат транзакции, и исключение создается повторно.If any of the calls to Delete fails, control is transferred to the Catch block where the transaction is rolled back and the exception re-thrown. Если все вызовы Delete успешно выполнены, транзакция фиксируется.If all calls to Delete succeed, then transaction is committed. Добавьте этот метод в класс ProductsBLL.Add this method to the ProductsBLL class.

Public Sub DeleteProductsWithTransaction _
    (ByVal productIDs As System.Collections.Generic.List(Of Integer))
    
    ' Start the transaction
    Adapter.BeginTransaction()
    Try
        ' Delete each product specified in the list
        For Each productID As Integer In productIDs
            Adapter.Delete(productID)
        Next
        ' Commit the transaction
        Adapter.CommitTransaction()
    Catch
        ' There was an error - rollback the transaction
        Adapter.RollbackTransaction()
        Throw
    End Try
End Sub

Применение транзакций для нескольких адаптеров таблицApplying Transactions Across Multiple TableAdapters

Код, связанный с транзакцией, в этом учебнике позволяет обрабатывать несколько инструкций в ProductsTableAdapter как атомарная операция.The transaction-related code examined in this tutorial allows for multiple statements against the ProductsTableAdapter to be treated as an atomic operation. Но что делать, если несколько изменений в разных таблицах базы данных должны выполняться атомарно?But what if multiple modifications to different database tables need to be performed atomically? Например, при удалении категории мы могли бы сначала переназначить ее текущие продукты другой категории.For instance, when deleting a category, we might first want to reassign its current products to some other category. Эти два действия переназначения продуктов и удаление категории должны выполняться как атомарная операция.These two steps reassigning the products and deleting the category should be executed as an atomic operation. Однако ProductsTableAdapter включает только методы для изменения таблицы Products и CategoriesTableAdapter включает только методы изменения таблицы Categories.But the ProductsTableAdapter includes only methods for modifying the Products table and the CategoriesTableAdapter includes only methods for modifying the Categories table. Итак, как транзакция может охватывать оба адаптера таблиц?So how can a transaction encompass both TableAdapters?

Один из вариантов — добавить метод в CategoriesTableAdapter с именем DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID) и использовать этот метод для вызова хранимой процедуры, которая переназначает продукты и удаляет категорию в области транзакции, определенной в хранимой процедуре.One option is to add a method to the CategoriesTableAdapter named DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID) and have that method call a stored procedure that both reassigns the products and deletes the category within the scope of a transaction defined within the stored procedure. В следующем учебном курсе мы рассмотрим, как начать, зафиксировать и откатить транзакции в хранимых процедурах.We'll look at how to begin, commit, and rollback transactions in stored procedures in a future tutorial.

Другой вариант — создать вспомогательный класс в DAL, который содержит метод DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID).Another option is to create a helper class in the DAL that contains the DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID) method. Этот метод создает экземпляр CategoriesTableAdapter и ProductsTableAdapter, а затем задает для этих двух адаптеров TableAdapter Connection свойства одному и тому же экземпляру SqlConnection.This method would create an instance of the CategoriesTableAdapter and the ProductsTableAdapter and then set these two TableAdapters Connection properties to the same SqlConnection instance. На этом этапе один из двух адаптеров таблицы TableAdapter инициирует транзакцию вызовом BeginTransaction.At that point, either one of the two TableAdapters would initiate the transaction with a call to BeginTransaction. Методы TableAdapter для повторного назначения продуктов и удаления категории будут вызываться в блоке Try...Catch с фиксацией или откатом транзакции по мере необходимости.The TableAdapters methods for reassigning the products and deleting the category would be invoked in a Try...Catch block with the transaction committed or rolled back as needed.

Шаг 4. Добавление методаUpdateWithTransactionк слою бизнес-логикиStep 4: Adding theUpdateWithTransactionMethod to the Business Logic Layer

На шаге 3 мы добавили метод UpdateWithTransaction в ProductsTableAdapter DAL.In Step 3 we added an UpdateWithTransaction method to the ProductsTableAdapter in the DAL. Необходимо добавить соответствующий метод к BLL.We should add a corresponding method to the BLL. Хотя уровень представления данных может вызывать DAL непосредственно для вызова метода UpdateWithTransaction, в этих учебниках было предусмотрено определение многоуровневой архитектуры, которая изолирует слой DAL от уровня представления.While the Presentation Layer could call directly down to the DAL to invoke the UpdateWithTransaction method, these tutorials have strived to define a layered architecture that insulates the DAL from the Presentation Layer. Поэтому мы наполнения, что мы будем продолжать этот подход.Therefore, it behooves us to continue this approach.

Откройте файл ProductsBLL класса и добавьте метод с именем UpdateWithTransaction, который просто вызывает соответствующий метод DAL.Open the ProductsBLL class file and add a method named UpdateWithTransaction that simply calls down to the corresponding DAL method. В ProductsBLLнеобходимо добавить два новых метода: UpdateWithTransaction, которые вы только что добавили, и DeleteProductsWithTransaction, которые были добавлены на шаге 3.There should now be two new methods in ProductsBLL: UpdateWithTransaction, which you just added, and DeleteProductsWithTransaction, which was added in Step 3.

Public Function UpdateWithTransaction _
    (ByVal products As Northwind.ProductsDataTable) As Integer
    
    Return Adapter.UpdateWithTransaction(products)
End Function
Public Sub DeleteProductsWithTransaction _
    (ByVal productIDs As System.Collections.Generic.List(Of Integer))
    
    ' Start the transaction
    Adapter.BeginTransaction()
    Try
        ' Delete each product specified in the list
        For Each productID As Integer In productIDs
            Adapter.Delete(productID)
        Next
        ' Commit the transaction
        Adapter.CommitTransaction()
    Catch
        ' There was an error - rollback the transaction
        Adapter.RollbackTransaction()
        Throw
    End Try
End Sub

Note

Эти методы не включают атрибут DataObjectMethodAttribute, назначенный большинству других методов в классе ProductsBLL, так как мы будем вызывать эти методы непосредственно из классов кода программной части страниц ASP.NET.These methods do not include the DataObjectMethodAttribute attribute assigned to most other methods in the ProductsBLL class because we'll be invoking these methods directly from the ASP.NET pages code-behind classes. Помните, что DataObjectMethodAttribute используется для отметки того, какие методы должны отображаться в мастере настройки источников данных ObjectDataSource и на каких вкладках (выбор, обновление, вставка или удаление).Recall that DataObjectMethodAttribute is used to flag what methods should appear in the ObjectDataSource s Configure Data Source wizard and under what tab (SELECT, UPDATE, INSERT, or DELETE). Поскольку в GridView отсутствует встроенная поддержка пакетного редактирования или удаления, нам придется вызывать эти методы программно, а не использовать декларативный подход без кода.Since the GridView lacks any built-in support for batch editing or deleting, we'll have to invoke these methods programmatically rather than use the code-free declarative approach.

Шаг 5. атомарное обновление данных из уровня представления данныхStep 5: Atomically Updating Database Data from the Presentation Layer

Чтобы проиллюстрировать воздействие транзакции на обновление пакета записей, давайте создадим пользовательский интерфейс, перечисляющий все продукты в GridView и включающий веб-элемент управления Button, который при нажатии переназначает продукты CategoryID значения.To illustrate the effect that the transaction has when updating a batch of records, let s create a user interface that lists all products in a GridView and includes a Button Web control that, when clicked, reassigns the products CategoryID values. В частности, переназначение категории будет продолжено, чтобы первым нескольким продуктам было присвоено допустимое CategoryID значения, в то время как другим пользователям намеренно назначено несуществующее значение CategoryID.In particular, the category reassignment will progress so that the first several products are assigned a valid CategoryID value while others are purposefully assigned a non-existent CategoryID value. При попытке обновить базу данных с помощью продукта, CategoryID которого не соответствует существующим категориям CategoryID, произойдет нарушение ограничения внешнего ключа и будет вызвано исключение.If we attempt to update the database with a product whose CategoryID does not match an existing category s CategoryID, a foreign key constraint violation will occur and an exception will be raised. В этом примере мы увидим, что при использовании транзакции исключение, вызванное нарушением ограничения внешнего ключа, приведет к откату предыдущего допустимого CategoryID изменений.What we'll see in this example is that when using a transaction the exception raised from the foreign key constraint violation will cause the previous valid CategoryID changes to be rolled back. Однако если транзакция не используется, изменения в исходных категориях останутся прежними.When not using a transaction, however, the modifications to the initial categories will remain.

Для начала откройте страницу Transactions.aspx в папке BatchData и перетащите элемент управления GridView с панели инструментов в конструктор.Start by opening the Transactions.aspx page in the BatchData folder and drag a GridView from the Toolbox onto the Designer. Задайте для его ID значение Products и, из своего смарт-тега, привяжите его к новому ObjectDataSource с именем ProductsDataSource.Set its ID to Products and, from its smart tag, bind it to a new ObjectDataSource named ProductsDataSource. Настройте ObjectDataSource для извлечения данных из GetProducts метода ProductsBLL классов.Configure the ObjectDataSource to pull its data from the ProductsBLL class s GetProducts method. Это будет элемент управления GridView, предназначенный только для чтения, поэтому установите в раскрывающихся списках на вкладках обновления, вставки и удаления значение (нет) и нажмите кнопку Готово.This will be a read-only GridView, so set the drop-down lists in the UPDATE, INSERT, and DELETE tabs to (None) and click Finish.

настроить ObjectDataSource для использования метода ProductsBLL класса sConfigure the ObjectDataSource to Use the ProductsBLL Class s GetProducts Method

Рис. 5. Настройка ObjectDataSource для использования метода GetProducts ProductsBLL Class (щелкните, чтобы просмотреть изображение с полным размером)Figure 5: Configure the ObjectDataSource to Use the ProductsBLL Class s GetProducts Method (Click to view full-size image)

установить в раскрывающихся списках на вкладках обновления, вставки и удаления значение (нет)Set the Drop-Down Lists in the UPDATE, INSERT, and DELETE Tabs to (None)

Рис. 6. Установка раскрывающихся списков на вкладках «обновить», «вставить» и «удалить» (нет) (щелкните, чтобы просмотреть изображение с полным размером)Figure 6: Set the Drop-Down Lists in the UPDATE, INSERT, and DELETE Tabs to (None) (Click to view full-size image)

После завершения работы мастера настройки источника данных Visual Studio создаст BoundFields и CheckBoxField для полей данных продукта.After completing the Configure Data Source wizard, Visual Studio will create BoundFields and a CheckBoxField for the product data fields. Удалите все эти поля, за исключением ProductID, ProductName, CategoryIDи CategoryName и переименуйте ProductName и CategoryName свойства BoundFields HeaderText на Product и Category соответственно.Remove all of these fields except for ProductID, ProductName, CategoryID, and CategoryName and rename the ProductName and CategoryName BoundFields HeaderText properties to Product and Category, respectively. В смарт-теге установите флажок Включить разбиение на страницы.From the smart tag, check the Enable Paging option. После внесения этих изменений декларативная разметка GridView и ObjectDataSource должна выглядеть следующим образом:After making these modifications, the GridView and ObjectDataSource s declarative markup should look like the following:

<asp:GridView ID="Products" runat="server" AllowPaging="True" 
    AutoGenerateColumns="False" DataKeyNames="ProductID" 
    DataSourceID="ProductsDataSource">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID" 
            InsertVisible="False" ReadOnly="True" 
            SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="Product" 
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" 
            SortExpression="CategoryID" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" 
            SortExpression="CategoryName" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>

Затем добавьте три веб-элемента управления "Кнопка" над элементом GridView.Next, add three Button Web controls above the GridView. Задайте для свойства Text в первой кнопке значение обновить сетку, второй — для изменения категорий (с ТРАНЗАКЦИей), а треть — для изменения категорий (без транзакции).Set the first Button s Text property to Refresh Grid, the second s to Modify Categories (WITH TRANSACTION), and the third one s to Modify Categories (WITHOUT TRANSACTION) .

<p>
    <asp:Button ID="RefreshGrid" runat="server" Text="Refresh Grid" />
</p>
<p>
    <asp:Button ID="ModifyCategoriesWithTransaction" runat="server"
        Text="Modify Categories (WITH TRANSACTION)" />
</p>
<p>
    <asp:Button ID="ModifyCategoriesWithoutTransaction" runat="server"
        Text="Modify Categories (WITHOUT TRANSACTION)" />
</p>

На этом этапе представление конструирования в Visual Studio должны выглядеть примерно так, как на снимке экрана, показанном на рис. 7.At this point the Design view in Visual Studio should look similar to the screen shot shown in Figure 7.

страница содержит элементы управления GridView и три кнопкиThe Page Contains a GridView and Three Button Web Controls

Рис. 7. страница содержит элементы управления GridView и три кнопки (щелкните, чтобы просмотреть изображение с полным размером)Figure 7: The Page Contains a GridView and Three Button Web Controls (Click to view full-size image)

Создайте обработчики событий для каждой из трех Click событий кнопок и используйте следующий код:Create event handlers for each of the three Button s Click events and use the following code:

Protected Sub RefreshGrid_Click _
    (ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles RefreshGrid.Click
    
    Products.DataBind()
End Sub
Protected Sub ModifyCategoriesWithTransaction_Click _
    (ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles ModifyCategoriesWithTransaction.Click
    
    ' Get the set of products
    Dim productsAPI As New ProductsBLL()
    Dim productsData As Northwind.ProductsDataTable = productsAPI.GetProducts()
    ' Update each product's CategoryID
    For Each product As Northwind.ProductsRow In productsData
        product.CategoryID = product.ProductID
    Next
    ' Update the data using a transaction
    productsAPI.UpdateWithTransaction(productsData)
    ' Refresh the Grid
    Products.DataBind()
End Sub
Protected Sub ModifyCategoriesWithoutTransaction_Click _
    (ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles ModifyCategoriesWithoutTransaction.Click
    
    ' Get the set of products
    Dim productsAPI As New ProductsBLL()
    Dim productsData As Northwind.ProductsDataTable = productsAPI.GetProducts()
    ' Update each product's CategoryID
    For Each product As Northwind.ProductsRow In productsData
        product.CategoryID = product.ProductID
    Next
    ' Update the data WITHOUT using a transaction
    Dim productsAdapter As New NorthwindTableAdapters.ProductsTableAdapter()
    productsAdapter.Update(productsData)
    ' Refresh the Grid
    Products.DataBind()
End Sub

Кнопка обновления Click обработчик событий просто повторно привязывает данные к GridView, вызвав метод Products GridView s DataBind.The refresh Button s Click event handler simply rebinds the data to the GridView by calling the Products GridView s DataBind method.

Второй обработчик событий переназначит продукты CategoryID s и использует новый метод транзакции из BLL для обновления базы данных в рамках транзакции.The second event handler reassigns the products CategoryID s and uses the new transaction method from the BLL to perform the database updates under the umbrella of a transaction. Обратите внимание, что каждый продукт CategoryID имеет произвольное значение, равное значению ProductID.Note that each product s CategoryID is arbitrarily set to the same value as its ProductID. Это будет прекрасно работать для первых нескольких продуктов, так как эти продукты имеют ProductID значения, которые должны быть сопоставлены с допустимыми CategoryID s.This will work fine for the first few products, since those products have ProductID values that happen to map to valid CategoryID s. Но после того, как ProductID запустится слишком много, это сокрытие ProductID s и CategoryID s больше не применяется.But once the ProductID s start getting too large, this coincidental overlap of ProductID s and CategoryID s no longer applies.

Третий обработчик событий Click обновляет продукты CategoryID s таким же образом, но отправляет обновление в базу данных с помощью метода Update по умолчанию ProductsTableAdapter s.The third Click event handler updates the products CategoryID s in the same manner, but sends the update to the database using the ProductsTableAdapter s default Update method. Этот метод Update не заключает в оболочку ряд команд внутри транзакции, поэтому эти изменения вносятся до первого обнаруженной ошибки нарушения ограничения внешнего ключа.This Update method does not wrap the series of commands within a transaction, so those changes are made prior to the first encountered foreign key constraint violation error will persist.

Чтобы продемонстрировать это поведение, посетите эту страницу в браузере.To demonstrate this behavior, visit this page through a browser. Сначала должна отобразиться первая страница данных, как показано на рис. 8.Initially you should see the first page of data as shown in Figure 8. Затем нажмите кнопку Изменить категории (с ТРАНЗАКЦИей).Next, click the Modify Categories (WITH TRANSACTION) button. Это вызовет обратную передачу и попытается обновить все продукты CategoryID значения, но приведет к нарушению ограничения внешнего ключа (см. рис. 9).This will cause a postback and attempt to update all of the products CategoryID values, but will result in a foreign key constraint violation (see Figure 9).

продукты отображаются в элементе управления GridView с страничным заполнениемThe Products are Displayed in a Pageable GridView

Рис. 8. продукты отображаются в элементе управления GridView (щелкните, чтобы просмотреть изображение с полным размером)Figure 8: The Products are Displayed in a Pageable GridView (Click to view full-size image)

переназначении категорий приводит к нарушению ограничения внешнего ключаReassigning the Categories Results in a Foreign Key Constraint Violation

Рис. 9. перераспределение категорий приводит к нарушению ограничения внешнего ключа (щелкните, чтобы просмотреть изображение с полным размером)Figure 9: Reassigning the Categories Results in a Foreign Key Constraint Violation (Click to view full-size image)

Теперь нажмите кнопку "назад" в браузере, а затем щелкните "обновить сетку".Now hit your browser s Back button and then click the Refresh Grid button. После обновления данных вы увидите те же выходные данные, что показаны на рис. 8.Upon refreshing the data you should see the exact same output as shown in Figure 8. То есть несмотря на то, что некоторые продукты CategoryID s были изменены на допустимые значения и обновлены в базе данных, они были отменены при нарушении ограничения внешнего ключа.That is, even though some of the products CategoryID s were changed to legal values and updated in the database, they were rolled back when the foreign key constraint violation occurred.

Теперь попробуйте нажать кнопку Изменить категории (без транзакции).Now try clicking the Modify Categories (WITHOUT TRANSACTION) button. Это приведет к ошибке нарушения ограничения внешнего ключа (см. рис. 9), но на этот раз откат этих продуктов, значения CategoryID которых были изменены на допустимое значение, не будет отменено.This will result in the same foreign key constraint violation error (see Figure 9), but this time those products whose CategoryID values were changed to a legal value will not be rolled back. Нажмите кнопку назад в браузере, а затем кнопку обновить сетку.Hit your browser s Back button and then the Refresh Grid button. Как показано на рис. 10, CategoryID s первых восьми продуктов были переназначены.As Figure 10 shows, the CategoryID s of the first eight products have been reassigned. Например, на рис. 8 изменено CategoryID 1, но на рис. 10 он был переназначен 2.For example, in Figure 8, Chang had a CategoryID of 1, but in Figure 10 it s been reassigned to 2.

, что значения CategoryID для некоторых продуктов были обновлены, а другие — нет.Some Products CategoryID Values were Updated While Others Were Not

Рис. 10. некоторые продукты CategoryID значения были обновлены, а другие — нет (щелкните, чтобы просмотреть изображение с полным размером)Figure 10: Some Products CategoryID Values were Updated While Others Were Not (Click to view full-size image)

СводкаSummary

По умолчанию методы TableAdapter не заключают выполненные инструкции базы данных в область транзакции, но с небольшой работой мы можем добавить методы, которые будут создавать, фиксировать и откатить транзакцию.By default, the TableAdapter s methods do not wrap the executed database statements within the scope of a transaction, but with a little work we can add methods that will create, commit, and rollback a transaction. В этом руководстве мы создали три таких метода в классе ProductsTableAdapter: BeginTransaction, CommitTransactionи RollbackTransaction.In this tutorial we created three such methods in the ProductsTableAdapter class: BeginTransaction, CommitTransaction, and RollbackTransaction. Мы увидели, как использовать эти методы вместе с блоком Try...Catch, чтобы сделать ряд инструкций по изменению данных атомарными.We saw how to use these methods along with a Try...Catch block to make a series of data modification statements atomic. В частности, мы создали метод UpdateWithTransaction в ProductsTableAdapter, который использует шаблон пакетного обновления для внесения необходимых изменений в строки указанного ProductsDataTable.In particular, we created the UpdateWithTransaction method in the ProductsTableAdapter, which uses the Batch Update pattern to perform the necessary modifications to the rows of a supplied ProductsDataTable. Мы также добавили метод DeleteProductsWithTransaction в класс ProductsBLL в BLL, который принимает в качестве входных данных List ProductID значений и вызывает метод непосредственных шаблонов DB Delete для каждого ProductID.We also added the DeleteProductsWithTransaction method to the ProductsBLL class in the BLL, which accepts a List of ProductID values as its input and calls the DB-Direct pattern method Delete for each ProductID. Оба метода начинаются с создания транзакции и последующего исполнения инструкций модификации данных в блоке Try...Catch.Both methods start by creating a transaction and then executing the data modification statements within a Try...Catch block. При возникновении исключения транзакция откатывается, в противном случае она фиксируется.If an exception occurs, the transaction is rolled back, otherwise it is committed.

На шаге 5 показан эффект транзакционных пакетных обновлений и пакетных обновлений, которые не используют транзакцию.Step 5 illustrated the effect of transactional batch updates versus batch updates that neglected to use a transaction. В следующих трех руководствах мы создадим основу, описанную в этом руководстве, и создадим пользовательские интерфейсы для выполнения пакетных обновлений, удалений и вставок.In the next three tutorials we will build upon the foundation laid in this tutorial and create user interfaces for performing batch updates, deletes, and inserts.

Поздравляем с программированием!Happy Programming!

Дополнительные материалыFurther Reading

Дополнительные сведения о разделах, обсуждаемых в этом руководстве, см. в следующих ресурсах:For more information on the topics discussed in this tutorial, refer to the following resources:

Об автореAbout the Author

Скотт Митчелл, автор семи книг по ASP/ASP. NET и основатель 4GuysFromRolla.com, работал с веб-технологиями Майкрософт с 1998.Scott Mitchell, author of seven ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Скотт работает как независимый консультант, преподаватель и модуль записи.Scott works as an independent consultant, trainer, and writer. Его последняя книга — Sams обучать себя ASP.NET 2,0 за 24 часа.His latest book is Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Он доступен по адресу mitchell@4GuysFromRolla.com.He can be reached at mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.or via his blog, which can be found at http://ScottOnWriting.NET.

Специальная благодарностьSpecial Thanks To

Эта серия руководств была рассмотрена многими полезными рецензентами.This tutorial series was reviewed by many helpful reviewers. Потенциальные рецензенты для этого руководства: Дейв Гарднер, Хилтон Гизнау и Терезой Мерфи.Lead reviewers for this tutorial were Dave Gardner, Hilton Giesenow, and Teresa Murphy. Хотите ознакомиться с моими будущими статьями MSDN?Interested in reviewing my upcoming MSDN articles? Если это так, расположите строку в mitchell@4GuysFromRolla.com.If so, drop me a line at mitchell@4GuysFromRolla.com.