트랜잭션 관리¶
데이터베이스 액세스에 있어서 트랜잭션 관리는 매우 중요한 요소 입니다. Fox DB Access 는 직관적이고 편리한 트랜잭션 API 를 제공하며 개발자는 이들 API 를 통해 전통적인 데이터베이스 액세스 방법보다 적은 노력과 시간으로 트랜잭션을 제어할 수 있습니다.
Note
트랜잭션 처리는 하나의 데이터베이스 연결만이 참여(enlist)하는 로컬 트랜잭션(local transaction)과 여러 데이터베이스 혹은 하나의 데이터베이스에 대한 여러 연결이 참여하는 분산 트랜잭션(distributed transaction)이 있습니다. 여기에서 다루는 트랜잭션은 로컬 트랜잭션이며 분산 트랜잭션에 대한 처리는 Fox Transactions을 참조 하십시요.
이 문서와 관련된 예제 코드는 다음 예제를 참조 하십시요.
- Fox Db Access Overview 예제 의 transaction_management 프로젝트
전통적인 트랜잭션 처리¶
전통적인 ADO.NET 기반의 코드에서 트랜잭션을 처리하는 코드를 먼저 살펴보고 Fox DB Access 의 트랜잭션 처리가 어떻게 다른지 살펴보도록 하겠습니다.
다음 코드는 PostgreSQL 에서 트랜잭션을 사용하여 INSERT
를 수행하는 코드입니다. 트랜잭션을 시작하기 위해서는 BeginTransaction
메서드를 호출해야 하고 이 메서드가 반환하는 IDbTransaction
객체, Npgsql 의 경우 NpgsqlTransaction
객체를 Command
객체의 Transation
속성에 할당해야 합니다. 이렇게 함으로써 Command
객체는 트랜잭션 내에서 쿼리를 수행하게 됩니다. 마지막으로 트랜잭션을 커밋하기 위해 Commit
메서드를 호출하거나 롤백하기 위해 Rollback
메서드를 호출합니다.
Note
대부분의 데이터베이스에서 하나의 SQL 문장 수행은 명시적으로 트랜잭션을 시작하지 않더라도 자동으로 트랜잭션이 시작되고 커밋/롤백 됩니다. 여기에서는 트랜잭션 설명을 위해서 명시적으로 트랜잭션을 시작하였습니다.
위 트랜잭션 코드의 문제점은 BeginTransaction
메서드가 반환하는 트랜잭션 객체(NpgsqlTransaction
)를 Command.Transaction
속성에 할당하여 쿼리가 트랜잭션에서 수행된다고 지정해야 한다는 것입니다. 그렇다면 BeginTransaction
메서드 호출 이후 트랜잭션 객체를 Transaction
속성에 할당하지 않은 쿼리를 수행하면 어떻게 될까요? 트랜잭션 바깥에서 쿼리가 수행될 것 처럼 보이지만 전혀 그렇지 않습니다. Npgsql 의 경우, BeginTransaction
메서드가 호출된 이후에 해당 연결을 사용하여 수행되는 모든 쿼리는 트랜잭션 내에서 수행되며 모두 커밋되거나 롤백될 것입니다. 즉, Npgsql 은 Command
객체의 Transaction
속성을 무시합니다.
더욱 문제가 되는 것은 Transaction
속성의 작동 방식이 데이터베이스 마다 다르다는 것입니다. Managed ODP.NET Core(Oracle)은 Npgsql 과 동일하게 Transaction
속성과 무관하게 BeginTransaction
메서드 호출과 Commit
/Rollback
메서드 호출 사이의 모든 쿼리를 하나의 트랜잭션으로 묶습니다. 한편 Microsoft.Data.SqlClient 는 트랜잭션을 사용하기 위해 Transaction
속성에 트랜잭션 객체를 반드시 할당해야 하며 BeginTransaction
메서드 호출 이후 Transaction
속성이 할당되지 않은 쿼리가 수행되면 예외를 유발합니다.
전통적인 트랜잭션 데이터액세스 코드는 불필요하게 트랜잭션 객체를 사용하여 코드를 복잡하게 만들며 데이터베이스마다 코딩 방식을 다르게 가져가야 한다는 문제가 있습니다.
Fox DB Access 트랜잭션 처리¶
FoxDBAccess
및 그 파생 클래스들은 트랜잭션 처리를 위해 다음 세 메서드를 제공합니다.
BeginTrans
: 트랜잭션을 시작합니다. 데이터베이스 연결은 명시적으로Open
된 상태이어야 합니다.CommitTrans
,RollbackTrans
메서드가 호출될 때까지Execute-
메서드들에 의해 수행되는 모든 쿼리는 트랜잭션에 참여합니다.CommitTrans
: 트랜잭션을 종료하고 변경 사항들을 모두 커밋합니다.RollbackTrans
: 트랜잭션을 종료하고 변경 사항들을 모두 롤백합니다.
FoxDbAccess
의 트랜잭션 사용법은 전통적인 트랜잭션 코드와 유사합니다. 하지만 BeginTrans
메서드가 트랜잭션 객체 반환하지도 않으며 Command.Transaction
속성에 트랜잭션 객체를 설정하는 작업도 필요하지 않습니다. 트랜잭션 객체는 FoxDbAccess
내부에서 관리되며 필요에 따라 자동으로 Transaction
속성에 할당합니다. 앞서 살펴본 전통적인 트랜잭션 처리 예제와 동등한 FoxDbAccess
기반의 트랜잭션 처리 코드 예제는 다음과 같습니다.
BeginTrans
메서드가 호출되면 내부적으로 BeginTransaction
메서드를 호출하고 이 메서드가 반환하는 트랜잭션 객체를 FoxDbAccess.DbTransaction
속성에 기록해 둡니다. 이 이후 Execute-
메서드들이 호출될 때 DbTransation
속성 값이 null
이 아닌 경우 이 값을 Command.Transaction
속성에 할당합니다. 이러한 방식으로 BeginTrans
메서드 호출과 CommitTrans
/RollbackTrans
메서드 호출 사이에 수행되는 쿼리들을 모두 트랜잭션에 참여 시키는 것입니다.
전통적인 트랜잭션 코드에 비해 FoxDbccess
기반 트랜잭션 코드의 다른점은 개발자가 트랜잭션 객체를 신경 쓸 필요가 없다는 점입니다. 또한 BeginTrans
메서드 호출과 CommitTrans
/RollbackTrans
메서드 호출 사이에 수행되는 모든 쿼리가 트랜잭션에 참여하기 때문에 직관적이며 데이터베이스 종류에 상관없이 일관적이라는 것입니다.
트랜잭션 관련 속성들¶
FoxDbAccess
클래스는 트랜잭션과 관련하여 두 속성을 제공합니다.
-
DbTransaction
BeginTrans
메서드 호출에 의해 생성된 트랜잭션 객체(IDbTransaction
) 입니다. 아직BeginTrans
메서드가 호출되지 않았거나CommitTrans
/RollbackTrans
메서드 호출이 완료된 후에는null
값을 반환합니다. 이 속성은 데이터베이스 종류에 독립적인 속성이므로IDbTransaction
타입의 객체를 반환합니다만 실제로는 어떤 데이터 프로바이더를 사용하는가에 따라NpgsqlTransaction
,OracleTransaction
,SqlTransaction
과 같은 구체적인 트랜잭션 객체 입니다.이 속성의 활용 대상은
CommandBuilder
와 같이FoxDbAccess
를 사용하지 않고 외부에서 생성한Command
객체를FoxDbAccess
가 시작한 트랜잭션 내에서 수행하고자 할 때 사용할 수 있습니다. -
IsInLocalTransaction
이 속성은
FoxDbAccess
객체가BeginTrans
메서드를 호출하여 트랜잭션을 진행 중인가를 나타냅니다. 매개변수로FoxDbAccess
를 받는 메서드에서 이미 트랜잭션이 시작된 상태로 그 메서드를 호출했는지 판단할 때 사용가능합니다.Warning
.net 환경에서 데이터베이스 트랜잭션은 앞서 살펴본 것과 같이
BeginTransaction
혹은BeginTrans
메서서드 호출을 통해 명시적으로 트랜잭션에 참여(enlist)하는 명시적 트랜잭션과TransactionScope
를 사용하여 암시적으로 트랜잭션에 참여하는 경우도 있습니다.IsInLocalTransaction
속성은DbTransation
속성의null
여부를 통해BeginTrans
호출 여부를 판단합니다. 따라서 암시적 트랜잭션이 사용되는 경우 현재 트랜잭션에 참여 중일 지라도IsInLocalTransaction
속성 값이false
일 수도 있습니다.
Summary¶
Fox DB Access 는 트랜잭션 처리를 위해 BeginTrans
/CommitTrans
/RollbackTrans
메서드를 제공합니다. BeginTrans
메서드를 호출하여 트랜잭션을 시작하고 이 이후 수행되는 모든 쿼리들이 트랜잭션 내에서 수행되도록 할 수 있습니다. 이 이후 CommitTrans
/RollbackTrans
메서드를 호출하여 트랜잭션을 커밋 하거나 롤백하면 됩니다. 이러한 Fox DB Access 의 트랜잭션 처리는 전통적인 트랜잭션 처리와 비교하여 직관적이며 데이터베이스 종류와 상관없이 일관적인 코딩 패턴을 제공합니다.