TransactionScope는 트랜잭션을 어떻게 롤백합니까?


99

여러 개체를 데이터베이스에 삽입 한 다음 내 메서드가 해당 개체를 검색하는지 확인하는 통합 테스트를 작성 중입니다.

데이터베이스에 대한 내 연결은 NHibernate를 통해 이루어지며 이러한 테스트를 만드는 일반적인 방법은 다음을 수행하는 것입니다.

NHibernateSession.BeginTransaction();

//use nhibernate to insert objects into database
//retrieve objects via my method
//verify actual objects returned are the same as those inserted

NHibernateSession.RollbackTransaction();

그러나 저는 최근에 바로이 목적으로 사용될 수있는 TransactionScope 에 대해 알게되었습니다 .

내가 찾은 몇 가지 예제 코드 는 다음과 같습니다.

public static int AddDepartmentWithEmployees(Department dept)
{

    int res = 0;

    DepartmentAdapter deptAdapter = new DepartmentAdapter();
    EmployeeAdapter empAdapter = new EmployeeAdapter();
    using (TransactionScope txScope = new TransactionScope())
    {

        res += deptAdapter.Insert(dept.DepartmentName);
        //Custom method made to return Department ID 
        //after inserting the department "Identity Column"
        dept.DepartmentID = deptAdapter.GetInsertReturnValue();
        foreach(Employee emp in dept.Employees)
        {

            emp.EmployeeDeptID = dept.DepartmentID;
            res += empAdapter.Insert(emp.EmployeeName, emp.EmployeeDeptID);

        }
        txScope.Complete();

    }
    return res;

}

나는 txScope.Complete()삽입 된 데이터가 롤백 될 줄 을 포함하지 않으면 믿습니다 . 그러나 불행히도 나는 그것이 어떻게 가능한지 이해하지 못합니다. txScope객체는 어떻게 데이터베이스 에서 deptAdapterempAdapter객체와 트랜잭션을 추적 합니까 ?

여기에 약간의 정보가 누락 된 것 같은 느낌이 듭니다.을 사용하여 내 코드를 둘러 쌈으로써 내 BeginTransaction()and RollbackTransaction() 호출 을 대체 할 수 TransactionScope있습니까?

그렇지 않은 경우 TransactionScope트랜잭션을 롤백 하는 방법은 무엇입니까?


저는 NHibernate를 사용한 적이 없지만 아마도이 링크 가 도움이 될 것입니다.

작업을 트랜잭션으로 그룹화하기 위해 NHibernate 세션을 관리하는 더 나은 방법을 찾고 있다면 해당 주제에 대한 내 블로그 게시물을 확인하십시오. dotnetchris.wordpress.com/2009/01/27/…
Chris Marisic

답변:


107

본질적으로 TransactionScope는 어댑터를 추적하지 않으며 데이터베이스 연결을 추적합니다. DB 연결을 열 때 연결은 주변 트랜잭션 (트랜잭션 범위)이 있는지 확인하고 참여하는 경우이를 확인합니다. 동일한 SQL 서버에 대한 연결이 하나 이상 있으면 Distribtued Transaction으로 에스컬레이션됩니다.

using 블록을 사용하고 있기 때문에 예외가 발생하더라도 dispose가 호출되도록 보장하는 일이 발생합니다. 따라서 txScope.Complete () 전에 dispose가 호출되면 TransactionScope는 트랜잭션 (또는 DTC)을 롤백하도록 연결에 알립니다.


10
TransactionScope는 스레드의 현재 트랜잭션을 제외하고는 아무것도 추적하지 않으며 모델을 기반으로해야하는 경우 수정합니다 (필요, 신규 필요 등). 트랜잭션은 데이터베이스 연결뿐만 아니라 참여하는 모든 것을 알립니다.
casperOne

1
나는 이것이 전적으로 사실이 아니라고 생각합니다. TransactionScope의 소스 코드를 부분적으로 추적했고 "트랜잭션을 생성하지 않았다면,"라는 이 msdn.microsoft.com/en-us/library/ms172152(v=vs.90).aspx 도 보았습니다 . 커밋은 CommittableTransaction 객체의 소유자가 커밋을 호출 할 때마다 발생합니다.이 시점에서 트랜잭션 관리자는 자원 관리자를 호출하고 TransactionScope 객체에서 Complete 메서드가 호출되었는지 여부에 따라 커밋 또는 롤백을 알립니다. " 소스 추적은 또한이 동작을 나타냅니다.
user44298 2011 년

:이 SO Q & A 유용하다고 IEnlistmentNotification
mungflesh

아직 명확하지 않습니다. 트랜잭션 범위 내에서 메서드가 호출 된 개체는 트랜잭션 메커니즘과 협력해야합니다. 시스템에서 Commit / Rollback 알림을 찾아야하며 필요할 때 롤백을 수행 할 수있는 알림이므로 스스로 롤백 할 수 있어야합니다 (파일 삭제가 실행 된 경우 분명히 우리가 가져 오지 않는 한 마법처럼 롤백 할 수 없습니다. 일부 예방 조치). 또한 SQL 서버 운영이 협조적인 것 같습니다. 그러나 .Net에 다른 협력 개체가 있습니까? 그리고 협동적인 수업을 작성하는 방법은 무엇입니까? 선적 서류 비치?

54

TransactionScope클래스 는 스레드 별 Transaction클래스 와 함께 작동합니다 .

TransactionScope가 생성 되면 Transaction스레드에 대한가 있는지 확인합니다 . 존재한다면 그것을 사용하고, 그렇지 않으면 새로운 것을 생성하여 스택에 푸시합니다.

기존의 것을 사용하는 경우 릴리스에 대한 카운터를 증가시킵니다 (호출해야하기 Dispose때문에). 마지막 릴리스 Transaction에서이 커밋되지 않은 경우 모든 작업을 롤백합니다.

클래스가 트랜잭션에 대해 마술처럼 아는 것처럼 보이는 이유는이 모델과 함께 작동하려는 클래스의 구현 세부 사항으로 남겨집니다.

deptAdapteremptAdapter인스턴스 를 만들 때 스레드에 현재 트랜잭션 ( 클래스 의 정적 Current속성)이 있는지 확인합니다 Transaction. 있는 경우 Transaction커밋 / 롤백 시퀀스에 참여하기 위해에 자신을 등록 합니다 (커밋 / 롤백 시퀀스 ( Transaction커널, 분산 등 다양한 트랜잭션 코디네이터 를 제어하고 전파 할 수 있음)에 참여합니다.


4
범위 내에서 생성 된 SqlConnection (s)과 어떻게 작동합니까? SqlConnection 클래스는 내부적으로 TransactionScope에 참여하는 Transaction 클래스를 사용합니까? 아니면 TLS에 직접 참여합니까?
Kakira 2014-08-08
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.