2011-09-09 4 views
0

응용 프로그램에서 다른 SQL 프로 시저를 사용하고 있습니다. 첫 번째 절차에서는 C# 코드에서 일부 처리를 삽입 한 다음 두 번째 절차 을 수행 한 다음 몇 가지 코드를 다시 처리하고 세 번째 절차에서 일부 레코드를 삭제 한 다음 새 레코드를 삽입합니다. 서버 1에서 모든 작업이 완료되면이 서버에서 데이터를 가져 와서 서버 2로 전송합니다. 레코드가 삭제되고 새 레코드가 삽입됩니다. 모든 프로 시저의 모든 서버에서 오류가있는 경우 모든 레코드를 롤백하고 싶습니다. 처리가 시간이 걸리고 다른 사용자가 동일한 테이블을 동시에 사용하기 때문에 테이블을 차단할 수 없기 때문에 begin trans를 사용할 수 없습니다. 그래서 친절하게도 다른 사용자를 위해 테이블을 차단하지 않고 어떻게 달성 할 수 있는지 말해주십시오.오류가 발생하면 다른 데이터베이스 서버에서 여러 쿼리를 롤백하는 방법

미리 감사드립니다.

편집 (코드 예제 추가) : 트랜잭션 범위를 시도했지만 연결을 여는 동안 예외가 발생했습니다. MS DTC를 구성했지만 올바르게 구성되지 않았을 수 있습니다.

"분산 트랜잭션 관리를위한 네트워크 액세스 (MSDTC)가 비활성화되었습니다. MSDTC 구성 요소 서비스 관리 도구를 사용하기위한 보안 구성에서 네트워크 액세스를 위해 DTC를 사용하십시오."

using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required)) 
    { 


     try 
     { 
      dl.SetBookReadyToLive(13570, false); 
      //SetBookReadyToLive 
      dl.AddTestSubmiitedTitleID(23402); 
      dl.AddBookAuthorAtLIve(13570, 1); 
      ts.Complete(); 

     } 
     catch (Exception ex) 
     { 
      Response.Write(ex.Message); 
     } 
    } 

공공 무효 SetBookReadyToLive (긴 bookID로서, 부울 상태) 는 { 시도 { 경우 (dbConMeta.State = ConnectionState.Open!) dbConMeta.Open();

  SqlCommand cmd = new SqlCommand("spSetBookReadyToLive", dbConMeta); 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Clear(); 
      cmd.Parameters.Add("@BookID", BookID); 
      cmd.Parameters.Add("@status", status); 
      cmd.ExecuteNonQuery(); 
      if (dbConMeta.State == ConnectionState.Open) 
       dbConMeta.Close(); 

     } 
     catch 
     { 
      if (dbConMeta.State == ConnectionState.Open) 
       dbConMeta.Close(); 

     } 

    } 

나는

내가 SQL 서버 2000, 난 내 PC에 또한 SQL 서버가 설치된 시스템에서 MS DTC의 구성을 설정 한 사용하고 있습니다> 방식의 연결을 여는에서 예외가 어디에서 코드를 실행하고 있는지. 그러나 여전히 같은 예외입니다.

답변

1

TransactionScope 클래스를 사용할 수 있습니다. 일반적으로 잘 작동하지만 분산 SQL 서버의 경우에는 두 서버 모두에서 MS DTC가 활성화되어 있고 올바르게 구성되어야합니다 (보안은 네트워크 트랜잭션, 분산 된 서버 등의 실행에 대해 부여되어야합니다 ...)

여기

MSDN의 예에서 복사 붙여 넣기, 당신은 "거의"이런 식으로 사용할 수 ... :)

// Create the TransactionScope to execute the commands, guaranteeing 
// that both commands can commit or roll back as a single unit of work. 
using (TransactionScope scope = new TransactionScope()) 
{ 
    using (SqlConnection connection1 = new SqlConnection(connectString1)) 
    { 
     // Opening the connection automatically enlists it in the 
     // TransactionScope as a lightweight transaction. 
     connection1.Open(); 

     // Create the SqlCommand object and execute the first command. 
     SqlCommand command1 = new SqlCommand(commandText1, connection1); 
     returnValue = command1.ExecuteNonQuery(); 
     writer.WriteLine("Rows to be affected by command1: {0}", returnValue); 

     // If you get here, this means that command1 succeeded. By nesting 
     // the using block for connection2 inside that of connection1, you 
     // conserve server and network resources as connection2 is opened 
     // only when there is a chance that the transaction can commit. 
     using (SqlConnection connection2 = new SqlConnection(connectString2)) 
     { 
      // The transaction is escalated to a full distributed 
      // transaction when connection2 is opened. 
      connection2.Open(); 

      // Execute the second command in the second database. 
      returnValue = 0; 
      SqlCommand command2 = new SqlCommand(commandText2, connection2); 
      returnValue = command2.ExecuteNonQuery(); 
      writer.WriteLine("Rows to be affected by command2: {0}", returnValue); 
     } 
    } 

    // The Complete method commits the transaction. If an exception has been thrown, 
    // Complete is not called and the transaction is rolled back. 
    scope.Complete(); 

} 

소스 : TransactionScope Class

최소화하기 위해 잠금을 사용하면 과부하로 IsolationLevel을 지정할 수 있습니다 TransactionScopeOptions를 취하는 생성자의 경우, ar e를 사용하면 ReadCommitted로 설정할 수 있습니다.

주 :이 DTC를 할 수있는 약간의 고통이기 때문에는 개인적으로 나는 절대적으로 필요하지 않는 한이 하나를 사용하지 않을 항상 구성 및 분산 트랜잭션 지역들보다 느린 일반적이지만 정말 BL/DAL에 따라 달라집니다 논리.

+0

David에게 도움을 청합니다. 위에 게시 된 원래 질문에 샘플 코드를 게시했습니다. 나는 거래 범위를 사용했다. 권한에 오류가 있습니다. 클라이언트 컴퓨터와 서버에서 MS DTC를 구성했지만 여전히 오류가 발생합니다. 위의 게시물을 다시 참조하십시오. 친절하게 도와주세요. 다시 한 번 감사드립니다.> –

+0

거의 다 왔습니다! 그냥 귀하의 오류 메시지에 대한 비트 구글과 당신은 ms dtc를 설정하고 실행하는 방법에 대한 단계별 가이드와 페이지를 찾을 수 있습니다. 네트워크 오류가 가장 일반적이며 보안 설정에서 마지막 항목을 터치하면됩니다. 미안 해요. 난 진흙탕을 기억하지 못합니다. –

0

짧은 답변 : MS SQL Management Studio에서 사용하는 것과 같은 방법입니다.

  1. 서버에 대한 연결을 엽니 다.
  2. 열기 특정 서버의 트랜잭션
  3. 당신은
  4. 당신은 당신이 ...
[다음 서버에 대해 1로 돌아가서] 동안 살아 연결을 유지해야합니다이 서버와 관련된 쿼리를 실행

모든 쿼리가 제대로 수행되면 변경 사항을 모두 커밋하십시오. 그렇지 않으면 모든 쿼리를 롤백하십시오.

경고 : 첫 번째 테이블은 모든 서버/쿼리를 완료 할 때까지 잠길 수 있습니다. 이 작업을 돕기 위해 여기에서 할 수있는 일 : 많은 양의 데이터가있는 경우 2 단계를 수행하기 전에 모든 서버의 임시 테이블로 데이터를 전송할 수 있습니다. 이 작업이 끝나면 트랜잭션을 열고 빠른 작업을 수행 한 다음 가능한 빨리 커밋/롤백합니다.

참고 : 테이블을 잠그지 않고이를 수행하는 방법을 묻는 이유는 무엇입니까? 그러므로 나는 "경고"부분에 아이디어를 추가했습니다.

관련 문제