2011-03-20 3 views
3

TransactionScope을 사용할 때 트랜잭션이 롤백되지 않는 문제가 있습니다.SQLite 인 메모리 데이터베이스 및 NHibernate를 사용하는 TransactionScope

우리는 메모리 인 SQLite 데이터베이스와 함께 NHibernate를 사용하고 있습니다. 그래서 우리는 응용 프로그램의 전체 수명 기간 동안 단 하나의 db 연결로 제한합니다 (이 경우, 일부 단위 테스트).

using (var ts = new TransactionScope(TransactionScopeOption.Required, 
            TimeSpan.Zero)) 
{ 
    using (var transaction = _repository.BeginTransaction()) 
    { 
     _repository.Save(entity); 
     transaction.Commit(); 
    } 
    // ts.Complete(); <- commented Complete call still commits transaction 
} 

NHibernate의 내부 중첩 트랜잭션을 제거하여 코드가 아래와 같이 간단하게 처리되는 경우에도 트랜잭션은 여전히 ​​커밋됩니다.

using (var ts = new TransactionScope(TransactionScopeOption.Required, 
            TimeSpan.Zero)) 
{  
    _repository.Save(entity);   
} // no Complete(), but the transaction still commits 

는 트랜잭션에 입대하기 위해서 TransactionScope 블록 내부 갓 열린 SQLite는 연결을 기다리고 있습니까?

다시 말해 데이터베이스 연결을 해제하기 때문에 새 연결을 제공 할 수 없습니다.

NHibernate 3.0과 SQLite 1.0.66.0을 사용하고 있습니다. 둘 다 최신 버전입니다.

참고 : NHibernate에 ITransaction 객체에 transaction.Rollback()를 사용가 제대로 작동하지 않는 것 바로 TransactionScope 지원의 트랜잭션을 롤백합니다.

+0

합니까 SQLite는 (및 드라이버) 지원 분산 트랜잭션을, 또는 명시 적입니다 TransactionScope를 알고 계셨습니까? –

+0

@diego : 예, SQLite ADO.NET 공급자 포럼의 게시물을 기반으로 TransactionScope는 몇 년 동안 지원되었습니다. "자동 분산 트랜잭션 참여"는 해당 홈페이지에서 언급 된 기능 중 하나입니다. – andreialecu

+0

범위를 끝내고 확인하면 데이터가 유지됩니까? –

답변

1

내가 그 이유를 찾은 것 같습니다. 연결이 TransactionScope 블록 내부에서 열리지 않으면 트랜잭션에 참여하지 않습니다.

여기에 몇 가지 정보가있다 : http://msdn.microsoft.com/en-us/library/aa720033(v=vs.71).aspx

솔루션 :

나는 이미 내 저장소에서 .BeginTransaction() 방법을했다, 그래서 나는 내가 수동으로이 주변 거래에서 연결을 입대 거라고 생각.

내가 함께 종료 코드입니다 :

/// <summary> 
    /// Begins an explicit transaction. 
    /// </summary> 
    /// <returns></returns> 
    public ITransaction BeginTransaction() 
    { 
     if (System.Transactions.Transaction.Current != null) 
     { 
      ((DbConnection) Session.Connection).EnlistTransaction(System.Transactions.Transaction.Current); 
     } 
     return Session.BeginTransaction(); 
    } 

그리고 여기 내가 사용하고 방법은 다음과 같습니다

using (var ts = new TransactionScope(TransactionScopeOption.Required, TimeSpan.Zero)) 
    using (var transaction = repository.BeginTransaction()) 
    { 
     repository.Save(entity); 
     transaction.Commit(); // nhibernate transaction is commited 
     // ts.Complete(); // TransactionScope is not commited 
    } // transaction is correctly rolled back now 
관련 문제