다음을 통해 공유


로컬 트랜잭션

적용 대상: .NET Framework .NET .NET Standard

ADO.NET 다운로드

ADO.NET의 트랜잭션은 여러 태스크를 함께 바인딩하여 단일 작업 단위로 실행되도록 하려는 경우에 사용됩니다. 예를 들어 애플리케이션이 두 가지 작업을 수행한다고 가정합니다. 먼저 응용 프로그램에서 주문 정보로 테이블을 업데이트합니다. 그런 다음, 응용 프로그램에서 재고 정보가 포함된 테이블을 업데이트하고 주문이 들어온 품목을 차변에 기입합니다. 두 작업 중 하나라도 실패하면 두 업데이트가 모두 롤백됩니다.

트랜잭션 유형 결정

트랜잭션이 단일 단계 트랜잭션이고 데이터베이스에서 직접 처리되는 경우 로컬 트랜잭션으로 간주됩니다. 트랜잭션이 트랜잭션 모니터로 조정되고 트랜잭션 확인에 2단계 커밋 같은 오류 없이 안전한 메커니즘을 사용할 경우 분산 트랜잭션으로 간주됩니다.

SQL Server용 Microsoft SqlClient 데이터 공급자에는 SQL Server 데이터베이스에서 로컬 트랜잭션을 수행하기 위한 자체 SqlTransaction 개체가 있습니다. 다른 .NET 데이터 공급자도 자체 Transaction 개체를 제공합니다. 또한 트랜잭션이 필요한 공급자 독립적인 코드를 작성하는 데 사용할 수 있는 DbTransaction 클래스가 있습니다.

참고 항목

트랜잭션은 서버에서 수행하는 것이 가장 효율적입니다. 명시적 트랜잭션을 폭넓게 사용하는 SQL Server 데이터베이스를 사용하는 경우 Transact-SQL BEGIN TRANSACTION 문을 사용하여 트랜잭션을 저장 프로시저로 작성하는 것이 좋습니다.

단일 연결을 사용하여 트랜잭션 수행

ADO.NET에서는 Connection 개체를 사용하여 트랜잭션을 제어합니다. BeginTransaction 메서드를 사용하면 로컬 트랜잭션을 시작할 수 있습니다. 트랜잭션이 시작되면 Transaction 개체의 Command 속성을 사용하여 해당 트랜잭션에 명령을 인리스트먼트할 수 있습니다. 그런 다음 트랜잭션 구성 요소의 성공 또는 실패에 따라 데이터 소스에서 수정된 내용을 커밋 또는 롤백할 수 있습니다.

참고 항목

EnlistDistributedTransaction 메서드는 로컬 트랜잭션에 사용할 수 없습니다.

트랜잭션의 범위는 연결로 제한됩니다. 다음 예제에서는 try 블록에서 두 개의 개별 명령으로 이루어진 명시적 트랜잭션을 수행합니다. 두 명령은 AdventureWorks SQL Server 샘플 데이터베이스에서 Production.ScrapReason 테이블에 대해 INSERT 문을 실행합니다. 이 작업은 예외가 throw되지 않을 경우 커밋됩니다. catch 블록의 코드는 예외가 발생하는 경우 트랜잭션을 롤백합니다. 트랜잭션이 완료되기 전에 트랜잭션이 중단되거나 연결이 끊어지면 트랜잭션이 자동으로 롤백됩니다.

예시

다음 단계를 사용하여 트랜잭션을 수행합니다.

  1. BeginTransaction 개체의 SqlConnection 메서드를 호출하여 트랜잭션의 시작을 표시합니다. BeginTransaction 메서드는 트랜잭션에 대한 참조를 반환합니다. 이 참조는 트랜잭션에 인리스트먼트된 SqlCommand 개체에 할당됩니다.

  2. TransactionTransaction 속성에 실행할 SqlCommand 개체를 할당합니다. Transaction 개체를 Transaction 개체의 Command 속성에 할당하지 않은 상태에서 활성 트랜잭션 연결로 명령을 실행하면 예외가 throw됩니다.

  3. 명령을 실행합니다.

  4. Commit 개체의 SqlTransaction 메서드를 호출하여 트랜잭션을 완료하거나 Rollback 메서드를 호출하여 트랜잭션을 종료합니다. Commit 또는 Rollback 메서드가 실행되기 전에 연결이 닫히거나 삭제되면 트랜잭션이 롤백됩니다.

다음 코드 예제에서는 SQL Server용 Microsoft SqlClient 데이터 공급자를 사용하여 트랜잭션 논리를 설명합니다.

using System;
using Microsoft.Data.SqlClient;

class Program
{
    static void Main(string[] args)
    {
        string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = AdventureWorks";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

            // Start a local transaction.
            SqlTransaction sqlTran = connection.BeginTransaction();

            // Enlist a command in the current transaction.
            SqlCommand command = connection.CreateCommand();
            command.Transaction = sqlTran;

            try
            {
                // Execute two separate commands.
                command.CommandText =
                  "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
                command.ExecuteNonQuery();
                command.CommandText =
                  "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
                command.ExecuteNonQuery();

                // Commit the transaction.
                sqlTran.Commit();
                Console.WriteLine("Both records were written to database.");
            }
            catch (Exception ex)
            {
                // Handle the exception if the transaction fails to commit.
                Console.WriteLine(ex.Message);

                try
                {
                    // Attempt to roll back the transaction.
                    sqlTran.Rollback();
                }
                catch (Exception exRollback)
                {
                    // Throws an InvalidOperationException if the connection
                    // is closed or the transaction has already been rolled
                    // back on the server.
                    Console.WriteLine(exRollback.Message);
                }
            }
        }
    }
}

참고 항목