2015-01-28 7 views
1

을 롤백하지 않습니다TransactionScope에 오류가 나는이 같은 주위 트랜잭션을 사용하여 트랜잭션을


using(TransactionScope tran = new TransactionScope()) { 
    CallAMethod1();//INSERT 
    CallAMethod2();//INSERT 
    tran.Complete(); 
} 

affected rows =-264 를 반환 CallAMethod2(); 방법은 그래서 그러나 처음 삽입이 최선을 다하고있다 삽입에 실패!

ambient transaction으로 작업하는 방법을 알고 싶습니다. 두 번째 방법에 내부 트랜잭션이 필요한 작업이 두 개 이상있는 경우 어떻게해야합니까? 이러한 작업을 내부 트랜잭션에 적용해야합니까? 이 같은 는 :

 DAL_Helper.Begin_Transaction(); 

       //------Fill newKeysDictioanry 

       affectedRow = DBUtilities.InsertEntityWithTrans("table2", newKeysDictioanry, DAL_Helper); 

       if (affectedRow == 1) 
       { 
        if (!string.IsNullOrEmpty(sp_confirm)) 
        { 
         result_dt = UserTransactionDAL.Run_PostConfirm_SP(sp_PostConfirm, OBJ.ValuesKey, DAL_Helper); 
         if (result_dt.Rows.Count > 0 && result_dt.Rows[0][0].ToString() == "0") 
         { 
          DAL_Helper.current_trans.Commit(); 

          if (DAL_Helper.connectionState == ConnectionState.Open) 
          { 
           DAL_Helper.Close_Connection(); 
          } 
          return 1;// affectedRow; 
         } 
         else 
         { 
          DAL_Helper.current_trans.Rollback(); 
          if (DAL_Helper.connectionState == ConnectionState.Open) 
          { 
           DAL_Helper.Close_Connection(); 
          } 
          return -2; 
         } 
        } 
//etc 
+0

데이터베이스는 트랜잭션 만들어 졌는지 여부를 알고 계십니까? Informix (Dynamic Server)는 트랜잭션이없고 로그인되고 버퍼에 기록되며 MODE ANSI가 트랜잭션 인 트랜잭션 로그가없는 데이터베이스를 지원합니다. 오류 -264는 임시 파일에 쓸 수 없습니다. 데이터베이스 서버를 실행중인 시스템에 문제가 있는지 여부를 알 수 없습니다. –

+0

@JonathanLeffler : 모르겠다. 이유가 무엇이든 두 번째 삽입 작업이 성공하지 못할 때 트랜잭션이 롤백되지 않는 이유는 무엇입니까? –

답변

5

1) 당신은 tran.Complete();가 호출되었는지 여부를 확인해야합니다. tran.Complete();이 호출되면 TransactionScope가 성공적으로 완료된 것으로 간주됩니다.

응용 프로그램이 모두가이 트랜잭션에서 수행하고자하는 작업을 완료 MSDN에서

, 당신은 는 트랜잭션을 커밋을 받아 들일 수 있다고 트랜잭션 매니저를 알리기 위해 한 번만 완료 메소드를 호출한다 . 이 메소드를 호출하지 못하면 트랜잭션이 중단됩니다.

tran.Complete();에 대한 호출은 트랜잭션을 완료하도록 트랜잭션 관리자에 알리는 것입니다. 실제로 트랜잭션 관리자는 Db 어댑터를 추적하지 않으며 연결 작업이 성공했는지 실패했는지 여부를 알지 못합니다. 예외가 트랜잭션 내에서 발생하지 않으면

: 응용 프로그램이 당신이 코드에서 tran.Complete();를 호출하지 않도록, 거래를 실패 Complete

How does TransactionScope roll back transactions?

를 호출하여 알려해야 범위 (즉, 사이에서 TransactionScope 개체 초기화 및 Dispose 메서드 호출) 사이에 범위 이 참여하는 트랜잭션이 진행될 수 있습니다. 트랜잭션 범위가 내에서 예외가 발생하면 트랜잭션 범위에 이 롤백됩니다. 당신이 작업이 실패 생각하는 경우 귀하의 경우에는

는, 어쩌면 당신은 그래서 tran.Complete();라는 하지하고 트랜잭션이 롤백하여 CallAMethod2();에 예외를 던질 수 있습니다.

2) 확인할 수있는 것은 연결이 트랜잭션에 등록되어 있는지 여부입니다. 연결이 등록되지 않은 경우 TransactionScope가 롤백되지 않습니다. 가능한 문제는 다음과 같습니다 연결이 트랜잭션 범위에 들어가기 전에 존재

  • 경우는 입대하지 않습니다 Does TransactionScope work with pre-existing connections?
  • 귀하의 기본 연결은 자동 입대를 지원하지 않습니다.두 번째 방법이 더 많은 경우 어떤

    : 두 번째 질문에 대해서는

    connection.EnlistTransaction(Transaction.Current) 
    

    : 이러한 경우

, 수동으로 연결을 입대 시도 할 수 있습니다 (위의 링크에서 추출) 내부 거래에서 이러한 조치를 취해야합니까 내부의 트랜잭션이 필요한 하나의 조치보다?

내가 정말 당신이 고려해야 여부에 따라 달라집니다 말을 당신은 트랜잭션 내부를 포장하지 않고 다른 곳에서 직접 호출 할 수 있습니다 의미 automic 동작으로 CallAMethod2();. 대부분의 경우 트랜잭션이 중첩 될 수 있으므로 내부 트랜잭션을 생성하는 것이 좋습니다.

하여 TransactionScope 클래스는 타입 TransactionScopeOption의 열거를 받아 여러 오버로드 된 생성자 를 제공 : 새로운 트랜잭션 범위를 만들 때 귀하의 경우에는, 또한 당신의 CallAMethod2();에서 TransactionScope에를 사용하는 것이 좋습니다, 우리는 몇 가지 옵션이 있습니다 범위의 트랜잭션 동작을 정의합니다. TransactionScope 개체에는 세 가지 옵션이 있습니다.

대기 트랜잭션에 가입하거나 존재하지 않으면 새로운 트랜잭션을 만듭니다.

새 루트 범위를 지정하십시오. 즉, 새 트랜잭션을 시작하고 해당 트랜잭션을 자체 범위 내의 새로운 주변 트랜잭션으로 사용하십시오.

거래에 전혀 참여하지 않습니다. 결과적으로 주위 트랜잭션이 없습니다.

어느 것이 실제로 응용 프로그램에 의존 하는가? 귀하의 경우, 첫 번째 옵션으로 갈 수 있다고 생각합니다. 다음은 예제입니다. MSDN

void RootMethod() 
{ 
    using(TransactionScope scope = new TransactionScope()) 
    { 
      /* Perform transactional work here */ 
      SomeMethod(); 
      scope.Complete(); 
    } 
} 

void SomeMethod() 
{ 
    using(TransactionScope scope = new TransactionScope()) 
    { 
      /* Perform transactional work here */ 
      scope.Complete(); 
    } 
} 
+0

: 트랜잭션 내에서 예외를 처리하지 않아 트랜잭션이 롤백되도록해야합니다. 예외 였어? –

+1

@just_name : 나는 당신이'CallAMethod2();'안에서 예외를 처리하지 않는다고 말하지 않았다. 예외 처리는 경우에 따라 다릅니다.방금 예외가 터지면'tran.Complete();'를 건너 뛸 것이라고 말했지만, 앱 로직을 모르기 때문에 자신의 케이스에서 이해가되는지 확신 할 수 없습니다. 핵심은 트랜잭션을 롤백하려는 경우'tran.Complete();가 호출되지 않도록해야한다는 것입니다. –

+0

Then 두 번째 방법에서 문제가 생겼을 때'tran.Complete();'가 호출되지 않도록 어떻게해야합니까? –

1

Khanh TO의 설명을 읽으십시오. 외부 트랜잭션 범위 외부에서 연결이 열리면 연결이 등록되지 않습니다.

그래서 두 번째 호출이 실패 할 때 첫 번째 호출이 롤백되지 않았습니다.

using (TransactionScope tran = new TransactionScope(TransactionScopeOption.Required)) 
{ 
    connection.EnlistTransaction(Transaction.Current); 
    CallAMethod1();//INSERT 
    CallAMethod2();//INSERT 
    tran.Complete(); 
} 
1

당신은 거래 범위는 내부 및 외부 사용할 수 있습니다 : 당신은 당신의 연결을 참여해야합니다

string connectionString = ConfigurationManager.ConnectionStrings["db"].ConnectionString; 
var option = new TransactionOptions 
{ 
    IsolationLevel = IsolationLevel.ReadCommitted, 
    Timeout = TimeSpan.FromSeconds(60) 
}; 
using (var scopeOuter = new TransactionScope(TransactionScopeOption.Required, option)) 
{ 
    using (var conn = new SqlConnection(connectionString)) 
    { 
     using (SqlCommand cmd = conn.CreateCommand()) 
     { 
      cmd.CommandText="INSERT INTO Data(Code, FirstName)VALUES('A-100','Mr.A')"; 
      cmd.Connection.Open(); 
      cmd.ExecuteNonQuery(); 
     } 
    } 
    using (var scopeInner = new TransactionScope(TransactionScopeOption.Required, option)) 
    { 
     using (var conn = new SqlConnection(connectionString)) 
     { 
      using (SqlCommand cmd = conn.CreateCommand()) 
      { 
       cmd.CommandText="INSERT INTO Data(Code, FirstName) VALUES('B-100','Mr.B')"; 
       cmd.Connection.Open(); 
       cmd.ExecuteNonQuery(); 
      } 
     } 
     scopeInner.Complete(); 
    } 
    scopeOuter.Complete(); 
}