.net의 거래


144

C # .Net 2.0에서 트랜잭션을 수행하는 가장 좋은 방법은 무엇입니까? 사용해야하는 수업은 무엇입니까? 커밋하고 롤백하는 모든 것들 등을 찾아야 할 함정은 무엇입니까? DB에 데이터를 삽입하는 동안 트랜잭션을 수행해야 할 프로젝트를 시작하고 있습니다. 거래에 대한 기본 사항에 대한 답변이나 링크는 환영합니다.


다음은 코드 프로젝트 에서 .NET 으로 트랜잭션을 시작으로 사용 하는 좋은 예입니다 .
Mitchel Sellers

답변:


271

두 가지 주요 거래 유형이 있습니다. 연결 트랜잭션 및 주변 트랜잭션. 연결 트랜잭션 (예 : SqlTransaction)은 db 연결 (예 : SqlConnection)에 직접 연결됩니다. 즉, 연결을 계속 전달해야합니다. 경우에 따라 OK이지만 "만들기 / 사용 / 릴리스"는 허용하지 않습니다. 크로스 DB 작업을 허용하지 않습니다. 예 (공백 형식) :

using (IDbTransaction tran = conn.BeginTransaction()) {
    try {
        // your code
        tran.Commit();
    }  catch {
        tran.Rollback();
        throw;
    }
}

너무 지저분하지는 않지만 연결 "conn"으로 제한됩니다. 다른 메소드를 호출하려면 "conn"을 전달해야합니다.

대안은 주변 거래입니다. .NET 2.0의 새로운 기능인 TransactionScope 개체 (System.Transactions.dll)는 다양한 작업에서 사용할 수 있습니다 (적절한 공급자는 주변 트랜잭션에 자동으로 참여 함). 이를 통해 기존 (트랜잭션이 아닌) 코드를 쉽게 개조하고 여러 공급자와 대화 할 수 있습니다 (여러 개와 대화 할 경우 DTC가 관여 할 수 있음).

예를 들면 다음과 같습니다.

using(TransactionScope tran = new TransactionScope()) {
    CallAMethodThatDoesSomeWork();
    CallAMethodThatDoesSomeMoreWork();
    tran.Complete();
}

여기서 두 가지 방법은 자체 연결 (개방 / 사용 / 닫기 / 처리)을 처리 할 수 ​​있지만 아무 것도 전달하지 않아도 자동으로 주변 트랜잭션의 일부가됩니다.

코드 오류가 발생하면 Dispose ()가 Complete ()없이 호출되므로 롤백됩니다. 내부 트랜잭션을 롤백 할 수는 없지만 외부 트랜잭션을 완료 할 수는 있지만 예상되는 중첩 등이 지원됩니다. 누군가가 불행한 경우 트랜잭션이 중단됩니다.

TransactionScope의 다른 장점은 데이터베이스에만 국한되지 않는다는 것입니다. 모든 트랜잭션 인식 공급자가 사용할 수 있습니다. 예를 들어 WCF. 또는 트랜잭션 스코프 호환 객체 모델도 있습니다 (예 : 롤백 기능이있는 .NET 클래스-아마도이 방법을 사용한 적이 없지만 메멘토보다 쉽습니다).

대체로 매우 유용한 객체입니다.

몇 가지주의 사항 :

  • SQL Server 2000에서 TransactionScope는 즉시 DTC로 이동합니다. 이것은 SQL Server 2005 이상에서 수정되었으며, DTC로 올라갈 때 2 개의 소스 등과 대화 할 때까지 LTM (훨씬 적은 오버 헤드)을 사용할 수 있습니다.
  • 연결 문자열을 조정해야 할 수도 있는 결함 이 있습니다.

CSLA .NET 2.0은 TransactionScope 객체를 지원합니다!
Binoj Antony

여기서 문제는 첫 번째 방법으로 트랜잭션이 있고이 방법 (캡슐화)이 부모 트랜잭션에서 호출되는지 여부를 알지 못하는 것입니다.
Eduardo Molteni

1
@Eduardo-TransactionScope를 사용할 때 문제가되지 않으므로 매우 매력적입니다. 이러한 트랜잭션은 중첩되고 가장 바깥 쪽 커밋 만 중첩됩니다.
Marc Gravell

나는 당신이 여전히 듣고 있기를 바랍니다. "일부 TransactionScope 호환 개체 모델이 있습니다"라고 말했습니다. 그들 중 일부를 가리킬 수 있습니까? 고마워.
majkinetor

1
다시 Marc, 또 다른 훌륭한 설명. '예상 중첩이 지원된다'고 말하면 메소드 내에 정의 된 트랜잭션 블록 (예 : CallAMethodThatDoesSomeWork ())에 대한 것입니까? 또는 transactionscope가 외부에 정의되어 있으면 필요하지 않습니까?
Phil Cooper

11
protected void Button1_Click(object sender, EventArgs e)
   {


       using (SqlConnection connection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database.mdf;Integrated Security=True;User Instance=True"))
       {
           connection1.Open();

           // Start a local transaction.
           SqlTransaction sqlTran = connection1.BeginTransaction();

           // Enlist a command in the current transaction.
           SqlCommand command = connection1.CreateCommand();
           command.Transaction = sqlTran;

           try
           {
               // Execute two separate commands.
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('a','b','c')";
               command.ExecuteNonQuery();
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('x','y','z')";
               command.ExecuteNonQuery();

               // Commit the transaction.
               sqlTran.Commit();
               Label3.Text = "Both records were written to database.";
           }
           catch (Exception ex)
           {
               // Handle the exception if the transaction fails to commit.
               Label4.Text = ex.Message;


               try
               {
                   // Attempt to roll back the transaction.
                   sqlTran.Rollback();
               }
               catch (Exception exRollback)
               {
                   // Throws an InvalidOperationException if the connection 
                   // is closed or the transaction has already been rolled 
                   // back on the server.
                   Label5.Text = exRollback.Message;

               }
           }
       }


   }

4

또한 트랜잭션을 자체 저장 프로 시저로 래핑하고 C # 자체에서 트랜잭션을 수행하는 대신 해당 방식으로 처리 할 수 ​​있습니다.


1

DB 관련 항목에 필요한 경우 일부 OR 매퍼 (예 : NHibernate)는 기본적으로 트랜스 액 티노를 기본적으로 지원합니다.


0

또한 필요한 것에 따라 다릅니다. 기본 SQL 트랜잭션의 경우 코드에서 BEGIN TRANS 및 COMMIT TRANS를 사용하여 TSQL 트랜잭션을 시도 할 수 있습니다. 이것이 가장 쉬운 방법이지만 복잡성이 있으므로 올바르게 커밋하고 롤백해야합니다.

나는 같은 것을 사용할 것이다

SQLTransaction trans = null;
using(trans = new SqlTransaction)
{
    ...
    Do SQL stuff here passing my trans into my various SQL executers
    ...
    trans.Commit  // May not be quite right
}

실패가 발생하면 using트랜잭션이 커밋되거나 롤백됩니다 (할 일에 따라 다름). 우리가 직면 한 가장 큰 문제는 항상 최선을 다하는 것입니다. 를 사용하면 거래 범위가 제한됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.