TransactionScope.Dispose 메서드

정의

트랜잭션 범위를 종료합니다.Ends the transaction scope.

public:
 virtual void Dispose();
public void Dispose ();
abstract member Dispose : unit -> unit
override this.Dispose : unit -> unit
Public Sub Dispose ()

구현

예제

다음 예제에서는 TransactionScope 클래스를 사용 하 여 트랜잭션에 참여할 코드 블록을 정의 하는 방법을 보여 줍니다.The following example demonstrates how to use the TransactionScope class to define a block of code to participate in a transaction.

// This function takes arguments for 2 connection strings and commands to create a transaction 
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the 
// transaction is rolled back. To test this code, you can connect to two different databases 
// on the same server by altering the connection string, or to another 3rd party RDBMS by 
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
    string connectString1, string connectString2,
    string commandText1, string commandText2)
{
    // Initialize the return value to zero and create a StringWriter to display results.
    int returnValue = 0;
    System.IO.StringWriter writer = new System.IO.StringWriter();

    try
    {
        // 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();
        }
    }
    catch (TransactionAbortedException ex)
    {
        writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
    }

    // Display messages.
    Console.WriteLine(writer.ToString());

    return returnValue;
}
'  This function takes arguments for 2 connection strings and commands to create a transaction 
'  involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the 
'  transaction is rolled back. To test this code, you can connect to two different databases 
'  on the same server by altering the connection string, or to another 3rd party RDBMS  
'  by altering the code in the connection2 code block.
Public Function CreateTransactionScope( _
  ByVal connectString1 As String, ByVal connectString2 As String, _
  ByVal commandText1 As String, ByVal commandText2 As String) As Integer

    ' Initialize the return value to zero and create a StringWriter to display results.
    Dim returnValue As Integer = 0
    Dim writer As System.IO.StringWriter = New System.IO.StringWriter

    Try
    ' Create the TransactionScope to execute the commands, guaranteeing
    '  that both commands can commit or roll back as a single unit of work.
        Using scope As New TransactionScope()
            Using connection1 As 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.
                Dim command1 As SqlCommand = 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 connection2 As 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
                    Dim command2 As SqlCommand = New SqlCommand(commandText2, connection2)
                    returnValue = command2.ExecuteNonQuery()
                    writer.WriteLine("Rows to be affected by command2: {0}", returnValue)
                End Using
            End Using

        ' The Complete method commits the transaction. If an exception has been thrown,
        ' Complete is called and the transaction is rolled back.
        scope.Complete()
        End Using
    Catch ex As TransactionAbortedException
        writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message)
    End Try

    ' Display messages.
    Console.WriteLine(writer.ToString())

    Return returnValue
End Function

설명

이 메서드를 호출 하면 트랜잭션 범위의 끝을 표시 합니다.Calling this method marks the end of the transaction scope. TransactionScope 개체가 트랜잭션을 만들고 범위에서 Complete를 호출한 경우에는이 메서드가 호출 될 때 TransactionScope 개체가 트랜잭션을 커밋하려고 시도 합니다.If the TransactionScope object created the transaction and Complete was called on the scope, the TransactionScope object attempts to commit the transaction when this method is called. 이 경우 트랜잭션 처리의 첫 번째 단계까지 메서드 블록이 완료 되었습니다.In this case, this method blocks until the first phase of transaction processing is complete. 첫 번째 단계는 트랜잭션의 모든 리소스 관리자 및 참여가 트랜잭션 결과에 대해 투표 하 고 TransactionManager에서 트랜잭션을 커밋하거나 지속적으로 결정 한 후에 종료 됩니다.The first phase ends after all resource managers and enlistments in the transaction have voted on the transaction outcome and the TransactionManager has durably decided to commit or abort the transaction. 처리의 두 번째 단계는 항상 비동기입니다.The second phase of processing is always asynchronous. 따라서 보장이 없습니다만 지정된 된 트랜잭션 내에서 커밋된 데이터 수 있는 즉시 나중에 다른 트랜잭션이이 데이터를 사용 하지 않는 경우.Therefore, there is no guarantee that data just committed from within a given transaction will be immediately available afterwards when not using another transaction to view this data.

C# using 생성을 사용 하면 예외가 발생 하더라도이 메서드가 호출 됩니다.The use of the C# using construction ensures that this method is called even if an exception occurs. 이 메서드를 호출한 후에 발생하는 예외는 트랜잭션에 영향을 주지 않습니다.Exceptions that occur after calling this method may not affect the transaction. 또한이 메서드 앰비언트 트랜잭션이 원래 상태를 복원합니다.This method also restores the ambient transaction to it original state. 트랜잭션이 실제로 커밋되지 않은 경우에는 TransactionAbortedException이 throw 됩니다.A TransactionAbortedException is thrown if the transaction is not actually committed.

이 메서드 차단 트랜잭션 처리의 첫 번째 단계 완료 될 때까지, 매우 주의 해야 응용 프로그램을 Windows Form (WinForm) 또는 교착 상태에서이 메서드를 사용 하는 경우 발생할 수 있습니다 때문에.Because this method blocks until the first phase of transaction processing is complete, you should be extremely careful when using this method in a Windows Form (WinForm) application, or a deadlock can occur. 하나의 WinForm 컨트롤 이벤트 내에서이 메서드를 호출 하는 경우 (예: 단추 클릭) 동기 Invoke 메서드를 사용 하 여 컨트롤에서 트랜잭션을 처리 하는 동안 일부 UI 작업 (예: 색 변경)을 수행 하도록 지시 하는 경우 교착 상태가 발생 합니다.If you call this method inside one WinForm Control event (for example, clicking a button), and use the synchronous Invoke method to direct the control to perform some UI tasks (for example, changing colors) in the middle of processing the transaction, a deadlock will happen. 이는 Invoke 메서드가 동기 이며 UI 스레드가 작업을 완료할 때까지 작업자 스레드를 차단 하기 때문입니다.This is because the Invoke method is synchronous and blocks the worker thread until the UI thread finishes its job. 그러나이 시나리오에서는 UI 스레드 대기 중 트랜잭션 커밋 작업자 스레드에 대 한 합니다.However, in our scenario, the UI thread is also waiting for the worker thread to commit the transaction. 결과 범위를 완료 하려면 커밋을 위해 무기한 대기를 계속할 수 없는 경우The result is that none is able to proceed and the scope waits indefinitely for the Commit to finish. 비동기 이므로 교착 상태가 발생 하기 쉽기 때문에 가능 하면 Invoke 대신 BeginInvoke를 사용 해야 합니다.You should use BeginInvoke rather than Invoke wherever possible, because it is asynchronous and thus less prone to deadlock.

이 메서드를 사용 하는 방법에 대 한 자세한 내용은 트랜잭션 범위를 사용 하 여 암시적 트랜잭션 구현 항목을 참조 하세요.For more information on how this method is used, see the Implementing An Implicit Transaction Using Transaction Scope topic.

적용 대상

추가 정보