ADO.NET 트랜잭션은 여러 작업을 함께 바인딩하여 단일 작업 단위로 실행하려는 경우에 사용됩니다. 예를 들어 애플리케이션이 두 가지 작업을 수행한다고 상상해 보십시오. 먼저 주문 정보를 사용하여 테이블을 업데이트합니다. 둘째, 주문된 항목을 인출하여 인벤토리 정보가 포함된 테이블을 업데이트합니다. 두 작업 중 하나가 실패하면 두 업데이트가 모두 롤백됩니다.
트랜잭션 유형 확인
트랜잭션은 단일 단계 트랜잭션이고 데이터베이스에서 직접 처리되는 경우 로컬 트랜잭션으로 간주됩니다. 트랜잭션은 트랜잭션 모니터에 의해 조정되고 트랜잭션 확인을 위해 장애로부터 안전한 메커니즘(예: 2단계 커밋)을 사용하는 경우 분산 트랜잭션으로 간주됩니다.
각 .NET Framework 데이터 공급자에는 로컬 트랜잭션을 수행하기 위한 고유한 Transaction 개체가 있습니다. SQL Server 데이터베이스에서 트랜잭션을 수행해야 하는 경우 트랜잭션을 System.Data.SqlClient 선택합니다. Oracle 트랜잭션의 경우 공급자를 System.Data.OracleClient 사용합니다. 또한 DbTransaction 트랜잭션이 필요한 공급자 독립적 코드를 작성하는 데 사용할 수 있는 클래스도 있습니다.
비고
트랜잭션은 서버에서 수행될 때 가장 효율적입니다. 명시적 트랜잭션을 광범위하게 사용하는 SQL Server 데이터베이스를 사용하는 경우 Transact-SQL BEGIN TRANSACTION 문을 사용하여 저장 프로시저로 작성하는 것이 좋습니다.
단일 연결을 사용하여 트랜잭션 수행
ADO.NET 개체를 사용하여 트랜잭션을 제어합니다 Connection .
BeginTransaction 메서드를 사용하여 로컬 트랜잭션을 시작할 수 있습니다. 트랜잭션을 시작한 후에는 Transaction 개체의 Command 속성을 사용하여 해당 트랜잭션에 명령을 등록할 수 있습니다. 그런 다음 트랜잭션 구성 요소의 성공 또는 실패에 따라 데이터 원본에서 수정한 내용을 커밋하거나 롤백할 수 있습니다.
비고
로컬 EnlistDistributedTransaction 트랜잭션에 메서드를 사용하면 안 됩니다.
트랜잭션 범위는 연결로 제한됩니다. 다음 예제에서는 블록에서 두 개의 별도 명령으로 구성된 명시적 트랜잭션을 try 수행합니다. 이 명령은 AdventureWorks SQL Server 샘플 데이터베이스의 Production.ScrapReason 테이블에 대해 INSERT 문을 실행합니다. 예외가 throw되지 않으면 커밋됩니다. 예외가 발생하면 catch 블록의 코드가 트랜잭션을 롤백합니다. 트랜잭션이 중단되거나 트랜잭션이 완료되기 전에 연결이 닫히면 자동으로 롤백됩니다.
예시
다음 단계에 따라 트랜잭션을 수행합니다.
개체의 BeginTransaction 메서드를 SqlConnection 호출하여 트랜잭션의 시작을 표시합니다. 메서드는 BeginTransaction 트랜잭션에 대한 참조를 반환합니다. 이 참조는 트랜잭션에 SqlCommand 참여하는 개체에 할당됩니다.
Transaction속성에 Transaction 개체를 할당하여 실행합니다. 활성 트랜잭션이 있는 연결에서 명령이 실행되고Transaction개체가Transaction개체의Command속성에 할당되지 않은 경우 예외가 발생합니다.필요한 명령을 실행합니다.
개체의 Commit 메서드를 SqlTransaction 호출하여 트랜잭션을 완료하거나 메서드를 Rollback 호출하여 트랜잭션을 종료합니다. 연결이 닫혀 있거나 메서드가 CommitRollback 실행되기 전에 삭제되면 트랜잭션이 롤백됩니다.
다음 코드 예제에서는 Microsoft SQL Server에서 ADO.NET 사용하는 트랜잭션 논리를 보여 줍니다.
using (SqlConnection connection = new(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);
}
}
}
Using connection As New SqlConnection(connectionString)
connection.Open()
' Start a local transaction.
Dim sqlTran As SqlTransaction = connection.BeginTransaction()
' Enlist a command in the current transaction.
Dim command As SqlCommand = 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 ex As Exception
' Handle the exception if the transaction fails to commit.
Console.WriteLine(ex.Message)
Try
' Attempt to roll back the transaction.
sqlTran.Rollback()
Catch exRollback As Exception
' Throws an InvalidOperationException if the connection
' is closed or the transaction has already been rolled
' back on the server.
Console.WriteLine(exRollback.Message)
End Try
End Try
End Using