트랜잭션 내에서 래핑된 데이터베이스 수정(VB)Wrapping Database Modifications within a Transaction (VB)

Scott Mitchellby Scott Mitchell

코드 다운로드 또는 PDF 다운로드Download Code or Download PDF

이 자습서는 데이터 일괄 처리의 업데이트, 삭제 및 삽입을 확인 하는 4 개 중 첫 번째입니다.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, UPDATEDELETE 문의 집합에 대해 원자성을 보장 하며 대부분의 최신 데이터베이스 시스템에서 지원 되는 기능입니다.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. S를 시작 하겠습니다.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. 뱅크는 첫 번째 단계에 성공 하지 못할 수 있지만 두 번째 단계가 실패 하는 경우 고객은 upset 당연히 수 있습니다.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 스크립트를 작성 하거나 저장 프로시저를 만들 때 또는 ADO.NET 또는 System.Transactions 네임 스페이스의 클래스를 사용 하 여 프로그래밍 방식으로 트랜잭션을 생성, 커밋 및 롤백하는 데 사용 되는 sql 문을 수동으로 입력할 수 있습니다.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

개발자는 System.Transactions 네임 스페이스의 TransactionScope 클래스 를 사용 하 여 트랜잭션 범위 내에서 일련의 문을 프로그래밍 방식으로 래핑하고, 서로 다른 두 데이터베이스 또는 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 (Microsoft DTC(Distributed Transaction Coordinator))를 사용 합니다.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.

ADO.NET에서 SqlClient 공급자를 사용 하는 경우 트랜잭션은 SqlTransaction 개체를 반환 하는 SqlConnection 클래스 BeginTransaction 메서드를 호출 하 여 시작 됩니다.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 블록의 문에서 오류가 발생 하면 실행이 SqlTransaction 개체 Rollback 메서드를 통해 트랜잭션을 롤백할 수 있는 catch 블록으로 전송 됩니다.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. 모든 문이 성공적으로 완료 되 면 try 블록의 끝에 SqlTransaction 개체 s Commit 메서드 를 호출 하면 트랜잭션이 커밋됩니다.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

기본적으로 형식화 된 데이터 집합의 Tableadapter는 트랜잭션을 사용 하지 않습니다.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 단계에서는 partial 클래스를 사용 하 여 이러한 메서드를 추가 하는 방법을 알아봅니다.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

SqlDataSource 관련 자습서에 대 한 ASP.NET 페이지 추가

그림 1: SqlDataSource 관련 자습서에 대 한 ASP.NET 페이지 추가Figure 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에 추가 합니다.Therefore, add this User Control to Default.aspx by dragging it from the Solution Explorer onto the page s Design view.

SectionLevelTutorialListing 사용자 정의 컨트롤을 Default.aspx에 추가 Add the SectionLevelTutorialListing.ascx User Control to Default.aspx

그림 2: Default.aspxSectionLevelTutorialListing.ascx 사용자 정의 컨트롤 추가 (전체 크기 이미지를 보려면 클릭)Figure 2: Add the SectionLevelTutorialListing.ascx User Control to Default.aspx (Click to view full-size image)

마지막으로, 이러한 4 개의 페이지를 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은 데이터를 저장 하는 반면 Tableadapter는 데이터베이스에서 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. Tableadapter는 데이터 업데이트를 위한 두 가지 패턴을 제공 합니다 .이를 일괄 업데이트 및 DB 직접 이라고 합니다.Recall that the TableAdapters provide two patterns for updating data, which I referred to as Batch Update and DB-Direct. 일괄 처리 업데이트 패턴을 사용 하 여 TableAdapter는 DataSet, DataTable 또는 Datarow의 컬렉션에 전달 됩니다.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. 그런 다음 DB 직접 패턴 메서드는 전달 된 값을 사용 하 여 적절 한 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. 기본적으로 TableAdapter에서 수행 하는 각 삽입, 업데이트 또는 삭제는 단일 불연속 작업으로 처리 됩니다.By default each insert, update, or delete performed by the TableAdapter is treated as a single discrete operation. 예를 들어, 데이터베이스에 10 개의 레코드를 삽입 하기 위해 BLL의 일부 코드에서 DB 직접 패턴을 사용 한다고 가정 합니다.For instance, imagine that the DB-Direct pattern is used by some code in the BLL to insert ten records into the database. 이 코드는 TableAdapter s Insert 메서드를 10 번 호출 합니다.This code would call the TableAdapter s Insert method ten times. 처음 5 개 삽입이 성공 하지만 여섯 번째 삽입이 예외를 발생 시킨 경우 처음 5 개의 삽입 된 레코드는 데이터베이스에 남아 있습니다.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. 이렇게 하려면 트랜잭션 상위에서 InsertCommand, UpdateCommandDeleteCommand를 실행 하는 새 메서드를 추가 하 여 TableAdapter를 수동으로 확장 해야 합니다.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. 데이터 액세스 계층을 만들partial 클래스 를 사용 하 여 형식화 된 데이터 집합 내에서 datatable의 기능을 확장 하는 방법을 살펴보았습니다.In Creating a Data Access Layer we looked at using partial classes to extend the functionality of the DataTables within the Typed DataSet. 이 기술은 Tableadapter와 함께 사용할 수도 있습니다.This technique can also be used with TableAdapters.

형식화 된 데이터 집합 Northwind.xsd App_Code 폴더 s DAL 하위 폴더에 있습니다.The Typed DataSet Northwind.xsd is located in the App_Code folder s DAL subfolder. TransactionSupport 이라는 DAL 폴더에 하위 폴더를 만들고 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.

TransactionSupport 라는 폴더와 이름이 Ststableadapter 인 클래스 파일을 추가 합니다.

그림 4: 이름이 TransactionSupport 폴더와 ProductsTableAdapter.TransactionSupport.vb 라는 클래스 파일 추가Figure 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 키워드는에 추가 된 멤버가 NorthwindTableAdapters 네임 스페이스의 ProductsTableAdapter 클래스에 추가 된다는 것을 컴파일러에 나타냅니다.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는 TableAdapter s 내부 SqlConnection를 열고 (필요한 경우) 트랜잭션을 시작 하 여 Transaction 속성에 할당 한 다음 해당 트랜잭션을 내부 SqlDataAdapter s SqlCommand 개체에 연결 합니다.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. CommitTransactionRollbackTransaction 내부 Rollback 개체를 닫기 전에 Transaction 개체 CommitConnection 메서드를 각각 호출 합니다.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. Adapter 개체 s Update 메서드를 호출 하면 예외가 발생할 경우 트랜잭션이 롤백되고 예외가 다시 throw 되는 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, UpdateCommandDeleteCommand s를 수행 하 여 Batch 업데이트 패턴을 구현 합니다.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

ProductsTableAdapter.TransactionSupport.vb의 partial 클래스를 통해 ProductsTableAdapter 클래스에 UpdateWithTransaction 메서드를 추가 합니다.Add the UpdateWithTransaction method to the ProductsTableAdapter class through the partial class in ProductsTableAdapter.TransactionSupport.vb. 또는 몇 가지 사소한 구문이 변경 된 상태에서이 메서드를 비즈니스 논리 계층 s ProductsBLL 클래스에 추가할 수 있습니다.Alternatively, this method could be added to the Business Logic Layer s ProductsBLL class with a few minor syntactical changes. 즉, Me.BeginTransaction(), Me.CommitTransaction()Me.RollbackTransaction()에서 Me 키워드를 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 메서드는 삭제할 ProductIDInteger형식의 List(Of T) 입력으로 받아들입니다.The DeleteProductsWithTransaction method accepts as input a List(Of T) of type Integer, which are the ProductID s to delete. 메서드는 BeginTransaction에 대 한 호출을 통해 트랜잭션을 시작한 다음 Try 블록에서 각 ProductID 값에 대해 DB 직접 패턴 Delete 메서드를 호출 하는 제공 된 목록을 반복 합니다.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 블록으로 제어가 전송 되 고 예외가 다시 throw 됩니다.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

여러 Tableadapter에서 트랜잭션 적용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. 그렇다면 트랜잭션은 Tableadapter를 어떻게 포함할 수 있나요?So how can a transaction encompass both TableAdapters?

한 가지 옵션은 메서드를 DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID) 라는 CategoriesTableAdapter에 추가 하 고 해당 메서드가 제품을 다시 할당 하 고 저장 프로시저 내에서 정의 된 트랜잭션 범위 내에서 범주를 삭제 하는 저장 프로시저를 호출 하도록 하는 것입니다.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.

다른 옵션은 DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID) 메서드를 포함 하는 DAL에서 도우미 클래스를 만드는 것입니다.Another option is to create a helper class in the DAL that contains the DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID) method. 이 메서드는 CategoriesTableAdapterProductsTableAdapter의 인스턴스를 만든 다음이 두 개의 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 단계에서는 DAL의 ProductsTableAdapterUpdateWithTransaction 메서드를 추가 했습니다.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을 분리 하는 계층화 된 아키텍처를 정의 하는 데 strived 있습니다.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. 따라서이 방법을 계속 behooves.Therefore, it behooves us to continue this approach.

ProductsBLL 클래스 파일을 열고 단순히 해당 DAL 메서드를 호출 하는 UpdateWithTransaction 라는 메서드를 추가 합니다.Open the ProductsBLL class file and add a method named UpdateWithTransaction that simply calls down to the corresponding DAL method. 이제 ProductsBLL에 두 가지 새로운 메서드가 있습니다. UpdateWithTransaction는 방금 추가한 것 이며 3 단계에서 추가 된 DeleteProductsWithTransaction입니다.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

이러한 메서드는 ASP.NET pages 코드 기반 클래스에서 직접 이러한 메서드를 호출 하기 때문에 ProductsBLL 클래스의 대부분의 다른 메서드에 할당 된 DataObjectMethodAttribute 특성을 포함 하지 않습니다.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의 데이터 원본 구성 마법사와 대상 탭 (SELECT, UPDATE, INSERT 또는 DELETE)에 표시 되어야 하는 메서드를 플래그 지정 하는 데 사용 됩니다.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의 모든 제품을 나열 하는 사용자 인터페이스를 만들고 클릭 하면 제품 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와 일치 하지 않는 제품을 사용 하 여 데이터베이스를 업데이트 하려고 하면 foreign key 제약 조건 위반이 발생 하 고 예외가 발생 합니다.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. 이 예에서는 트랜잭션을 사용할 때 foreign key 제약 조건 위반으로 인해 발생 하는 예외가 발생 하면 이전의 유효한 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.

먼저 BatchData 폴더에서 Transactions.aspx 페이지를 열고 GridView를 도구 상자에서 디자이너로 끌어 옵니다.Start by opening the Transactions.aspx page in the BatchData folder and drag a GridView from the Toolbox onto the Designer. 해당 ID Products로 설정 하 고 스마트 태그에서 ProductsDataSource라는 새 ObjectDataSource에 바인딩합니다.Set its ID to Products and, from its smart tag, bind it to a new ObjectDataSource named ProductsDataSource. ProductsBLL 클래스 s GetProducts 메서드에서 데이터를 가져오도록 ObjectDataSource를 구성 합니다.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.

ProductsBLL 클래스 s GetProducts 메서드를 사용 하도록 ObjectDataSource를 구성 Configure the ObjectDataSource to Use the ProductsBLL Class s GetProducts Method

그림 5: ProductsBLL 클래스 s GetProducts 메서드를 사용 하도록 ObjectDataSource 구성 (전체 크기 이미지를 보려면 클릭)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, CategoryIDCategoryName를 제외 하 고 이러한 필드를 모두 제거 하 고 ProductNameCategoryName 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 및 3 개의 단추 웹 컨트롤이 포함 되어 있습니다.The Page Contains a GridView and Three Button Web Controls

그림 7: GridView 및 3 개의 단추 웹 컨트롤 (전체 크기 이미지를 보려면 클릭)이 페이지에 포함 되어 있습니다.Figure 7: The Page Contains a GridView and Three Button Web Controls (Click to view full-size image)

세 개의 단추 s 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

Refresh 단추 Click 이벤트 처리기는 Products GridView s DataBind 메서드를 호출 하 여 단순히 데이터를 GridView에 다시 바인딩합니다.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. 각 제품 CategoryIDProductID와 동일한 값으로 임의로 설정 됩니다.Note that each product s CategoryID is arbitrarily set to the same value as its ProductID. 이러한 제품은 유효한 CategoryID에 매핑하기 위해 발생 하는 ProductID 값을 가지 므로 처음 몇 개 제품에 대해 제대로 작동 합니다.This will work fine for the first few products, since those products have ProductID values that happen to map to valid CategoryID s. 그러나 ProductID s가 너무 커지면 ProductID s와 CategoryID가 더 이상 적용 되지 않습니다.But once the ProductID s start getting too large, this coincidental overlap of ProductID s and CategoryID s no longer applies.

세 번째 Click 이벤트 처리기는 동일한 방식으로 CategoryID s 제품을 업데이트 하지만 ProductsTableAdapter의 기본 Update 메서드를 사용 하 여 데이터베이스에 업데이트를 보냅니다.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 값이 업데이트 되지만 foreign key 제약 조건 위반이 발생 합니다 (그림 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)

범주를 다시 할당 Foreign Key 제약 조건 위반이 발생 합니다.Reassigning the Categories Results in a Foreign Key Constraint Violation

그림 9: 범주를 다시 할당 하면 Foreign Key 제약 조건 위반이 발생 합니다 (전체 크기 이미지를 보려면 클릭).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 제품 중 일부가 올바른 값으로 변경 되 고 데이터베이스에서 업데이트 되더라도 foreign key 제약 조건 위반이 발생 했을 때 롤백됩니다.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. 이렇게 하면 동일한 foreign key 제약 조건 위반 오류가 발생 합니다 (그림 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에 표시 된 것 처럼 처음 8 개 제품의 CategoryID는 다시 할당 됩니다.As Figure 10 shows, the CategoryID s of the first eight products have been reassigned. 예를 들어 그림 8에서 파일과는 1 CategoryID 했지만 그림 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, CommitTransactionRollbackTransaction의 세 가지 메서드를 만들었습니다.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. 특히 제공 된 ProductsDataTable의 행에 대해 필요한 수정 작업을 수행 하기 위해 Batch 업데이트 패턴을 사용 하는 ProductsTableAdapter``UpdateWithTransaction 메서드를 만들었습니다.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 메서드를 BLL의 ProductsBLL 클래스에 추가 했습니다 .이 클래스는 ProductID 값의 List을 입력으로 수락 하 고 각 Delete에 대해 DB 직접 패턴 메서드 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

Scott Mitchell(7 개의 ASP/ASP. NET books 및 4GuysFromRolla.com창립자)은 1998부터 Microsoft 웹 기술을 사용 하 여 작업 했습니다.Scott Mitchell, author of seven ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Scott은 독립 컨설턴트, 강사 및 기록기로 작동 합니다.Scott works as an independent consultant, trainer, and writer. 최신 책은 24 시간 이내에 ASP.NET 2.0을 sams teach yourself것입니다.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. 이 자습서의 리드 검토자는 Dave Gardner, Hilton Gid Esenow 및 Teresa Murphy 였습니다.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.