2010-05-26 5 views
31

문제가있어서 발견 한 모든 기사 나 예제가 신경 쓰이는 것 같습니다.catch 블록에서 롤백 할 SqlTransaction 개체에 액세스 할 수 없습니다.

트랜잭션에서 일부 데이터베이스 작업을 수행하려고합니다. 내가 뭘 원하는 대부분의 예와 매우 유사하다 :

using (SqlConnection Conn = new SqlConnection(_ConnectionString)) 
{ 
    try 
    { 
     Conn.Open(); 
     SqlTransaction Trans = Conn.BeginTransaction(); 

     using (SqlCommand Com = new SqlCommand(ComText, Conn)) 
     { 
      /* DB work */ 
     } 
    } 
    catch (Exception Ex) 
    { 
     Trans.Rollback(); 
     return -1; 
    } 
} 

그러나 문제는 SqlTransaction Transtry 블록 내에서 선언 된 것입니다. 따라서 catch() 블록에서 액세스 할 수 없습니다. 대부분의 예제는 try 블록 전에 Conn.Open()Conn.BeginTransaction()을 처리하지만, 둘 다 여러 예외를 throw 할 수 있기 때문에 조금 위험하다고 생각합니다.

내가 잘못 했나요? 아니면 대부분의 사람들이이 위험을 무시합니까? 예외가 발생하는 경우 롤백 할 수있는 가장 좋은 솔루션은 무엇입니까?

+2

P. 예외를 throw하는 대신 -1 (오류 코드)을 반환 하시겠습니까? –

답변

55
using (var Conn = new SqlConnection(_ConnectionString)) 
{ 
    SqlTransaction trans = null; 
    try 
    { 
     Conn.Open(); 
     trans = Conn.BeginTransaction(); 

     using (SqlCommand Com = new SqlCommand(ComText, Conn, trans)) 
     { 
      /* DB work */ 
     } 
     trans.Commit(); 
    } 
    catch (Exception Ex) 
    { 
     if (trans != null) trans.Rollback(); 
     return -1; 
    } 
} 

또는 당신도 깨끗하고 쉽게 이동이 사용할 수 있습니다

using (var Conn = new SqlConnection(_ConnectionString)) 
{ 
    try 
    { 
     Conn.Open(); 
     using (var ts = new System.Transactions.TransactionScope()) 
     { 
      using (SqlCommand Com = new SqlCommand(ComText, Conn)) 
      { 
       /* DB work */ 
      } 
      ts.Complete(); 
     } 
    } 
    catch (Exception Ex) 
    {  
     return -1; 
    } 
} 
+0

두 번째 버전은 예외가 발생했을 때 실제로 롤백을 수행합니까? 편집 : 좋아, 내가 그것을 본 문서를 읽은 후. – Marks

+1

첫 번째 예에서 sqlcommand가 트랜잭션과 연결되도록 지정하지 않아도됩니까? '(SqlCommand Com = 새로운 SqlCommand (ComText, Conn, ** trans **))'을 사용하고 있습니까? 아니면 불필요한가? 내재적으로 연관되어 있습니까? –

+0

예, 감사합니다. TransactionScope를 사용하면 그렇지 않지만 첫 번째 예제에서는 생략했습니다. 그에 따라 편집 됨. –

6

BTW 사용이

using (SqlConnection Conn = new SqlConnection(_ConnectionString)) 
{ 
    SqlTransaction Trans = null; 
    try 
    { 
     Conn.Open(); 
     Trans = Conn.BeginTransaction(); 

     using (SqlCommand Com = new SqlCommand(ComText, Conn)) 
     { 
      /* DB work */ 
     } 
    } 
    catch (Exception Ex) 
    { 
     if (Trans != null) 
      Trans.Rollback(); 
     return -1; 
    } 
} 

- 당신은 성공적인 처리의 경우를 저 지르지 않은

1

Microsoft 샘플로 시도/캐치 외부로 전송 시작 ​​see this msdn link. BeginTransaction 메서드는 예외를 throw하거나 트랜잭션을 시작하지만 둘 다 결코 시작하지 않아야한다고 가정합니다 (설명서에서 불가능하다고 말하지는 않지만). 그래서 this link

3
using (SqlConnection Conn = new SqlConnection(_ConnectionString)) 
{ 
    try 
    { 
     Conn.Open(); 
     SqlTransaction Trans = Conn.BeginTransaction(); 

     try 
     { 
      using (SqlCommand Com = new SqlCommand(ComText, Conn)) 
      { 
       /* DB work */ 
      } 
     } 
     catch (Exception TransEx) 
     { 
      Trans.Rollback(); 
      return -1; 
     } 
    } 
    catch (Exception Ex) 
    { 
     return -1; 
    } 
} 
+0

코드 작성이 더 많지만, 각 단계가 실패하는 이유를 판별 할 수있는 최상의 세분성을 제공합니다. 그러나 SqlCommand는 트랜잭션과 연결되어야합니다. – JWilliams

8

내가 유형을 입력하고 null로 변수를 설정 좋아하지 않는다 :

그러나, 당신은 당신을 위해 많은 (그리) 무거운 관리 TransactionScope를 사용하여 더 나은 될 수있다 :

try 
{ 
    using (var conn = new SqlConnection(/* connection string or whatever */)) 
    { 
     conn.Open(); 

     using (var trans = conn.BeginTransaction()) 
     { 
      try 
      { 
       using (var cmd = conn.CreateCommand()) 
       { 
        cmd.Transaction = trans; 
        /* setup command type, text */ 
        /* execute command */ 
       } 

       trans.Commit(); 
      } 
      catch (Exception ex) 
      { 
       trans.Rollback(); 
       /* log exception and the fact that rollback succeeded */ 
      } 
     } 
    } 
} 
catch (Exception ex) 
{ 
    /* log or whatever */ 
} 

그리고 MySql 또는 다른 제공 업체로 전환하려면 1 줄만 수정하면됩니다.

0
SqlConnection conn = null; 
SqlTransaction trans = null; 

try 
{ 
    conn = new SqlConnection(_ConnectionString); 
    conn.Open(); 
    trans = conn.BeginTransaction(); 
    /* 
    * DB WORK 
    */ 
    trans.Commit(); 
} 
catch (Exception ex) 
{ 
    if (trans != null) 
    { 
     trans.Rollback(); 
    } 
    return -1; 
} 
finally 
{ 
    if (conn != null) 
    { 
     conn.Close(); 
    } 
} 
관련 문제