2013-10-17 4 views
1

I가 다른 서버에 하나 개의 서버에서 데이터를 복사하는 다음 코드를트랜잭션을 롤백 할 수 없습니다 :이 SqlTransaction이 완료

private static string CopyData(string sourceConnection, string targetConnection, bool push = true) 
{ 
    string result = "Copy started"; 
    SqlConnection source = new SqlConnection(sourceConnection); 
    SqlConnection target = new SqlConnection(targetConnection); 
    SqlTransaction targetTransaction; 

    source.Open(); 
    target.Open(); 

    if (source.State != ConnectionState.Open || target.State != ConnectionState.Open) 
    { 
     throw new Exception("Unable to connect to server at this time."); 
    } 

    targetTransaction = target.BeginTransaction(); 

    try 
    { 
     ClearTable(target, targetTransaction, "TableAAA"); 
     ClearTable(target, targetTransaction, "TableBBB"); 

     CopyTable(source, target, targetTransaction, "TableAAA"); 
     CopyTable(source, target, targetTransaction, "TableBBB"); 

     targetTransaction.Commit(); 
     result = "Copy successful"; 
    } 
    catch (Exception E) 
    { 
     targetTransaction.Rollback(); 
     result = "An SQL Error has occurred. Unable to copy data at this time.\n\n" + E.Message;    
    } 
    finally 
    { 
     target.Close(); 
     source.Close(); 
    } 

    return result; 
} 

private static void ClearTable(SqlConnection destination, SqlTransaction tran, string table) 
{ 
    SqlCommand cmd = new SqlCommand(string.Format("DELETE FROM {0}", table), destination); 
    cmd.Transaction = tran; 
    cmd.ExecuteNonQuery(); 
} 

private static void CopyTable(SqlConnection source, SqlConnection destination, SqlTransaction tran, string table) 
{ 
    SqlCommand cmd = new SqlCommand(string.Format("DELETE FROM {0}", table), destination);    
    cmd.Transaction = tran; 
    cmd.ExecuteNonQuery(); 

    cmd = new SqlCommand(string.Format("SELECT * FROM {0}", table), source); 
    SqlDataReader reader = cmd.ExecuteReader(); 

    SqlBulkCopy bulkData = new SqlBulkCopy(destination, SqlBulkCopyOptions.Default, tran); 
    bulkData.DestinationTableName = table; 
    bulkData.BulkCopyTimeout = (int)Properties.Settings.Default.CommandTimeOut; 
    bulkData.WriteToServer(reader); 

    bulkData.Close(); 
    reader.Close(); 
} 

나는 테이블 중 하나의 스키마를 변경하여 오류를 강제하는 경우, 변경 내용을 롤백하려고하면 "이 SqlTransaction이 완료되었습니다."라는 오류 메시지가 나타납니다. 이 문제를 어떻게 수정하고 왜 그런 일이 발생합니까?

답변

2

정확한 문제는 확실하지 않지만 using 문을 사용하는 방식으로 코드를 다시 작성하는 것이 좋습니다. 이렇게하면 연결을 명시 적으로 닫거나 트랜잭션을 롤백 할 필요가 없습니다.

private static string CopyData(string sourceConnection, string targetConnection, bool push = true) 
{  
    using (var source = new SqlConnection(sourceConnection)) 
    using (var target = new SqlConnection(targetConnection)) 
    { 
     source.Open(); 
     target.Open(); 

     // no need to check for open status, as Open will throw an exception if it fails 

     using (var transaction = target.BeginTransaction()) 
     { 
      // do work 

      // no need to rollback if exception occurs 
      transaction.Commit(); 
     } 

     // no need to close connections explicitly 
    } 
} 
관련 문제