トランザクション スコープを使用した暗黙的なトランザクションの実装Implementing an Implicit Transaction using Transaction Scope

TransactionScope クラスを使用すると、コード ブロックがトランザクションに参加しているものとして簡単にマークすることができ、トランザクション自体と対話する必要がありません。The TransactionScope class provides a simple way to mark a block of code as participating in a transaction, without requiring you to interact with the transaction itself. トランザクション スコープは、アンビエント トランザクションを自動的に選択して管理することができます。A transaction scope can select and manage the ambient transaction automatically. トランザクション アプリケーションを開発する際は、使いやすさと効率の点から、TransactionScope クラスを使用することをお勧めします。Due to its ease of use and efficiency, it is recommended that you use the TransactionScope class when developing a transaction application.

また、リソースをトランザクションに明示的に参加させる必要がありません。In addition, you do not need to enlist resources explicitly with the transaction. System.Transactions リソース マネージャー (SQL Server 2005 など) は、スコープによって作成されたアンビエント トランザクションを検出して、自動的に参加することができます。Any System.Transactions resource manager (such as SQL Server 2005) can detect the existence of an ambient transaction created by the scope and automatically enlist.

トランザクション スコープの作成Creating a transaction scope

次のサンプルは、TransactionScope クラスの簡単な使用法を示しています。The following sample shows a simple usage of the TransactionScope class.

// 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);
    }
    catch (ApplicationException ex)
    {
        writer.WriteLine("ApplicationException 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)
    Catch ex As ApplicationException
        writer.WriteLine("ApplicationException Message: {0}", ex.Message)
    End Try

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

    Return returnValue
End Function

新規に作成すると、トランザクション スコープが開始されてTransactionScopeオブジェクト。The transaction scope is started once you create a new TransactionScope object. コード サンプルに示すようには、スコープで作成することをお勧めしますが、を使用してステートメントです。As illustrated in the code sample, it is recommended that you create scopes with a using statement. を使用してステートメントが使用できるは、c# と Visual basic での両方と同様に機能するtry… 最後に破棄されるように、スコープが正常にブロックします。The using statement is available both in C# and in Visual Basic, and works like a try...finally block to ensure that the scope is disposed of properly.

TransactionScope をインスタンス化すると、参加するトランザクションがトランザクション マネージャーによって決定されます。When you instantiate TransactionScope, the transaction manager determines which transaction to participate in. いったん決定されると、このスコープは常にそのトランザクションに参加します。Once determined, the scope always participates in that transaction. 2 つの要因に基づいて決定された: の値と、アンビエント トランザクションが存在するかどうか、 TransactionScopeOptionコンス トラクターのパラメーターです。The decision is based on two factors: whether an ambient transaction is present and the value of the TransactionScopeOption parameter in the constructor. アンビエント トランザクションとは、実行するコードが含まれているトランザクションのことです。The ambient transaction is the transaction within which your code executes. Transaction.Current クラスの静的 Transaction プロパティを呼び出すことによってアンビエント トランザクションへの参照を取得できます。You can obtain a reference to the ambient transaction by calling the static Transaction.Current property of the Transaction class. このパラメーターの使用方法の詳細については、次を参照してください。、 TransactionScopeOption を使用してトランザクション フローを管理するこのトピックの「します。For more information on how this parameter is used, see the Managing transaction flow using TransactionScopeOption section of this topic.

トランザクション スコープの完了Completing a transaction scope

アプリケーションがトランザクション内で実行する必要のあるすべての作業を完了したら、トランザクションをコミットできることをトランザクション マネージャーに知らせるために、Complete メソッドを一度だけ呼び出す必要があります。When your application completes all the work it wants to perform in a transaction, you should call the Complete method only once to inform the transaction manager that it is acceptable to commit the transaction. 呼び出しを配置することを非常に良好であるCompleteの最後のステートメントとして、を使用してブロックします。It is very good practice to put the call to Complete as the last statement in the using block.

このメソッドの呼び出しに失敗すると、トランザクション マネージャーがこのシステムの障害、またはトランザクションのスコープ内でスローされる例外には、それと同等としてに解釈するために、トランザクションが中止します。Failing to call this method aborts the transaction, because the transaction manager interprets this as a system failure, or equivalent to an exception thrown within the scope of the transaction. ただし、このメソッドを呼び出したからといって必ずしもトランザクションのコミットが保証されるわけではありません。However, calling this method does not guarantee that the transaction wil be committed. これはトランザクション マネージャーにステータスを通知する手段にすぎません。It is merely a way of informing the transaction manager of your status. Complete メソッドを呼び出した後は、Current プロパティを使用してアンビエント トランザクションにアクセスできなくなります。アクセスしようとすると例外がスローされます。After calling the Complete method, you can no longer access the ambient transaction by using the Current property, and attempting to do so will result in an exception being thrown.

場合、TransactionScopeオブジェクトのトランザクションを最初に、作成されたトランザクション マネージャーによってトランザクションのコミットの実際の作業が内のコードの最後の行の後に発生、を使用してブロックします。If the TransactionScope object created the transaction initially, the actual work of committing the transaction by the transaction manager occurs after the last line of code in the using block. このオブジェクトによってトランザクションが作成されていない場合、Commit オブジェクトの所有者によって CommittableTransaction が呼び出されるたびにコミットが発生します。If it did not create the transaction, the commit occurs whenever Commit is called by the owner of the CommittableTransaction object. トランザクション マネージャーのリソース マネージャーを呼び出してその時点でとをコミットまたはロールバック、に基づいてかどうかを知らせる、Completeでメソッドが呼び出されました、TransactionScopeオブジェクト。At that point the transaction manager calls the resource managers and informs them to either commit or rollback, based on whether the Complete method was called on the TransactionScope object.

を使用してステートメントにより、Disposeのメソッド、TransactionScope例外が発生した場合でも、オブジェクトが呼び出されます。The using statement ensures that the Dispose method of the TransactionScope object is called even if an exception occurs. Dispose メソッドは、トランザクション スコープの末尾を表します。The Dispose method marks the end of the transaction scope. このメソッドの呼び出し後に発生した例外は、トランザクションに影響しない場合があります。Exceptions that occur after calling this method may not affect the transaction. また、このメソッドはアンビエント トランザクションを前の状態に復元します。This method also restores the ambient transaction to it previous state.

スコープがトランザクションを作成し、そのトランザクションが中止された場合は、TransactionAbortedException がスローされます。A TransactionAbortedException is thrown if the scope creates the transaction, and the transaction is aborted. トランザクション マネージャーがコミットを判断できない場合は、TransactionInDoubtException がスローされます。A TransactionInDoubtException is thrown if the transaction manager cannot reach a Commit decision. トランザクションがコミットされた場合は、例外はスローされません。No exception is thrown if the transaction is committed.

トランザクションのロールバックRolling back a transaction

トランザクションをロールバックする場合は、トランザクション スコープ内で Complete メソッドを呼び出さないようにしてください。If you want to rollback a transaction, you should not call the Complete method within the transaction scope. たとえば、スコープ内で例外をスローすると、For example, you can throw an exception within the scope. スコープが参加しているトランザクションがロールバックされます。The transaction in which it participates in will be rolled back.

TransactionScopeOption を使用してトランザクション フローを管理します。Managing transaction flow using TransactionScopeOption

次の例にある TransactionScope メソッドのように、独自のスコープを使用するメソッド内から、RootMethod を使用するメソッドを呼び出すことによって、トランザクション スコープを入れ子にすることができます。Transaction scope can be nested by calling a method that uses a TransactionScope from within a method that uses its own scope, as is the case with the RootMethod method in the following example,

void RootMethod()  
{  
     using(TransactionScope scope = new TransactionScope())  
     {  
          /* Perform transactional work here */  
          SomeMethod();  
          scope.Complete();  
     }  
}  

void SomeMethod()  
{  
     using(TransactionScope scope = new TransactionScope())  
     {  
          /* Perform transactional work here */  
          scope.Complete();  
     }  
}  

最上位のトランザクション スコープをルート スコープと呼びます。The top-most transaction scope is referred to as the root scope.

TransactionScope クラスには、スコープのトランザクション動作を定義する TransactionScopeOption 型の列挙体を受け入れる、いくつかのオーバーロードされたコンストラクターがあります。The TransactionScope class provides several overloaded constructors that accept an enumeration of the type TransactionScopeOption, which defines the transactional behavior of the scope.

TransactionScope オブジェクトには次の 3 つのオプションがあります。A TransactionScope object has three options:

  • アンビエント トランザクションに参加します (存在しない場合は新規に作成します)。Join the ambient transaction, or create a new one if one does not exist.

  • 新しいルート スコープになります。つまり、新しいトランザクションを開始して、そのトランザクションをそれ自身のスコープ内の新しいアンビエント トランザクションにします。Be a new root scope, that is, start a new transaction and have that transaction be the new ambient transaction inside its own scope.

  • どのトランザクションにも参加しません。Not take part in a transaction at all. その結果、アンビエント トランザクションは存在しません。There is no ambient transaction as a result.

スコープが Required でインスタンス化された場合、アンビエント トランザクションが存在しているときは、スコープはそのトランザクションに参加します。If the scope is instantiated with Required, and an ambient transaction is present, the scope joins that transaction. 一方、アンビエント トランザクションが存在しないときは、スコープは新しいトランザクションを作成して、ルート スコープになります。If, on the other hand, there is no ambient transaction, then the scope creates a new transaction, and become the root scope. これが既定値です。This is the default value. Required を使用した場合、スコープがルートのときでも、アンビエント トランザクションに参加するだけのときでも、スコープ内のコードは異なる動作をする必要がありません。When Required is used, the code inside the scope does not need to behave differently whether it is the root or just joining the ambient transaction. いずれの場合にもスコープ内のコードは同じ動作をします。It should operate identically in both cases.

スコープが RequiresNew でインスタンス化された場合は、常にルート スコープです。If the scope is instantiated with RequiresNew, it is always the root scope. スコープが新しいトランザクションを開始し、そのトランザクションがスコープ内の新しいアンビエント トランザクションになります。It starts a new transaction, and its transaction becomes the new ambient transaction inside the scope.

スコープが Suppress でインスタンス化された場合は、アンビエント トランザクションの有無にかかわらず、スコープがトランザクションに参加することはありません。If the scope is instantiated with Suppress, it never takes part in a transaction, regardless of whether an ambient transaction is present. 常にこの値でインスタンス化されるスコープがnullそのアンビエント トランザクションとします。A scope instantiated with this value always have null as its ambient transaction.

上記のオプションを要約すると、次の表のようになります。The above options are summarized in the following table.

TransactionScopeOptionTransactionScopeOption アンビエント トランザクションAmbient Transaction スコープの参加The scope takes part in
必須Required いいえNo 新規トランザクション (ルートになる)New Transaction (will be the root)
RequiresNewRequires New いいえNo 新規トランザクション (ルートになる)New Transaction (will be the root)
SuppressSuppress いいえNo トランザクションなしNo Transaction
必須Required はいYes アンビエント トランザクションAmbient Transaction
RequiresNewRequires New はいYes 新規トランザクション (ルートになる)New Transaction (will be the root)
SuppressSuppress はいYes トランザクションなしNo Transaction

TransactionScope オブジェクトが既存のアンビエント トランザクションに参加した場合、スコープ オブジェクトを破棄してもトランザクションが終了しないことがあります (スコープがトランザクションを中止した場合を除く)。When a TransactionScope object joins an existing ambient transaction, disposing of the scope object may not end the transaction, unless the scope aborts the transaction. アンビエント トランザクションがルート スコープによって作成されたものである場合は、ルート スコープが破棄されたときのみ、トランザクションの Commit が呼び出されます。If the ambient transaction was created by a root scope, only when the root scope is disposed of, does Commit get called on the transaction. トランザクションが手動で作成されたものである場合は、中止されるか、その作成者によってコミットされたときに、そのトランザクションは終了します。If the transaction was created manually, the transaction ends when it is either aborted, or committed by its creator.

次の例は、入れ子になった 3 つのスコープ オブジェクトを作成する TransactionScope オブジェクトを示しています。各スコープ オブジェクトは異なる TransactionScopeOption 値でインスタンス化しています。The following example shows a TransactionScope object that creates three nested scope objects, each instantiated with a different TransactionScopeOption value.

using(TransactionScope scope1 = new TransactionScope())   
//Default is Required   
{   
     using(TransactionScope scope2 = new   
      TransactionScope(TransactionScopeOption.Required))   
     {  
     ...  
     }   

     using(TransactionScope scope3 = new TransactionScope(TransactionScopeOption.RequiresNew))   
     {  
     ...  
     }   

     using(TransactionScope scope4 = new   
        TransactionScope(TransactionScopeOption.Suppress))   
    {  
     ...  
    }   
}  

このコード例では、アンビエント トランザクションがない状態で、新しいスコープ scope1Required で作成しています。The example shows a code block without any ambient transaction creating a new scope (scope1) with Required. スコープ scope1 は、新しいトランザクション (トランザクション A) を作成し、トランザクション A をアンビエント トランザクションにするため、ルート スコープになります。The scope scope1 is a root scope as it creates a new transaction (Transaction A) and makes Transaction A the ambient transaction. その後、Scope1 は、それぞれ異なる TransactionScopeOption 値を持つオブジェクトをさらに 3 つ作成します。Scope1 then creates three more objects, each with a different TransactionScopeOption value. たとえば、scope2Required で作成されますが、アンビエント トランザクションがあるため、scope1 によって作成された最初のトランザクションに参加します。For example, scope2 is created with Required, and since there is an ambient transaction, it joins the first transaction created by scope1. scope3 は新しいトランザクションのルート スコープです。scope4 にはアンビエント トランザクションがありません。Note that scope3 is the root scope of a new transaction, and that scope4 has no ambient transaction.

TransactionScopeOption の既定値でかつ最もよく使用される値は Required ですが、その他の各値にはそれぞれ固有の用途があります。Although the default and most commonly used value of TransactionScopeOption is Required, each of the other values has its unique purpose.

Suppress は、コード セクションで実行された操作を保持したり、操作が失敗した場合でもアンビエント トランザクションを中止しない場合に役立ちます。Suppress is useful when you want to preserve the operations performed by the code section, and do not want to abort the ambient transaction if the operations fail. たとえば、ログの記録や監査操作を実行する場合や、アンビエント トランザクションがコミットしても中止してもサブスクライバーにイベントを公開する場合などです。For example, when you want to perform logging or audit operations, or when you want to publish events to subscribers regardless of whether your ambient transaction commits or aborts. 次の例で示すように、この値を使用すれば、トランザクション スコープ内に非トランザクション コード セクションを置くことができます。This value allows you to have a non-transactional code section inside a transaction scope, as shown in the following example.

using(TransactionScope scope1 = new TransactionScope())  
{  
     try  
     {  
          //Start of non-transactional section   
          using(TransactionScope scope2 = new  
             TransactionScope(TransactionScopeOption.Suppress))  
          {  
               //Do non-transactional work here  
          }  
          //Restores ambient transaction here  
   }  
     catch  
     {}  
   //Rest of scope1  
}  

入れ子になったスコープ内での選択Voting inside a nested scope

入れ子になったスコープはルート スコープのアンビエント トランザクションに参加できますが、入れ子になったスコープ内で Complete を呼び出してもルート スコープには影響がありません。Although a nested scope can join the ambient transaction of the root scope, calling Complete in the nested scope has no affect on the root scope. ルート スコープから、入れ子になった最後のスコープまで、すべてのスコープがトランザクションのコミットを選択した場合にのみ、トランザクションはコミットされます。Only if all the scopes from the root scope down to the last nested scope vote to commit the transaction, will the transaction be committed. 入れ子になったスコープで Complete を呼び出さないと、アンビエント トランザクションが即時に中止されるため、ルート スコープに影響します。Not calling Complete in a nested scope will affect the root scope as the ambient transaction will immediately be aborted.

TransactionScope タイムアウトの設定Setting the TransactionScope timeout

TransactionScope のオーバーロードされたコンストラクターのいくつかは、トランザクションのタイムアウトを制御するために使用される TimeSpan 型の値を受け入れます。Some of the overloaded constructors of TransactionScope accept a value of type TimeSpan, which is used to control the timeout of the transaction. タイムアウトをゼロに設定すると、タイムアウトは無期限になります。A timeout set to zero means an infinite timeout. 無期限のタイムアウトは主にデバッグに役立ちます。つまり、コードをステップ実行することによってビジネス ロジックの問題を切り分け、問題の究明を試みている間はデバッグするトランザクションがタイムアウトにならないようにすることができます。Infinite timeout is useful mostly for debugging, when you want to isolate a problem in your business logic by stepping through your code, and you do not want the transaction you debug to time out while you attempt to locate the problem. タイムアウト値を無期限にすると、トランザクションのデッドロックに対する保護機能が無効になるため、上記以外の目的でこれを使用する場合は十分注意する必要があります。Be extremely careful using the infinite timeout value in all other cases, because it overrides the safeguards against transaction deadlocks.

次の 2 つの場合は、通常、TransactionScope タイムアウトを既定以外の値に設定します。You typically set the TransactionScope timeout to values other than default in two cases. 第 1 は、開発時に、中止されたトランザクションをアプリケーションがどう処理するかをテストする場合です。The first is during development, when you want to test the way your application handles aborted transactions. タイムアウトを小さい値 (1 ミリ秒など) に設定すると、トランザクションが失敗するため、エラー処理コードを確認できます。By setting the timeout to a small value (such as one millisecond), you cause your transaction to fail and can thus observe your error handling code. 第 2 は、スコープがリソース競合に関与した結果、デッドロックの発生が考えられるときに、既定のタイムアウト値より小さい値に設定する場合です。The second case in which you set the value to be less than the default timeout is when you believe that the scope is involved in resource contention, resulting in deadlocks. この場合は、できるだけ早くトランザクションを中止して、既定のタイムアウトが満了するのを待ちません。In that case, you want to abort the transaction as soon as possible and not wait for the default timeout to expire.

アンビエント トランザクションに参加するスコープが、アンビエント トランザクションのタイムアウト設定値より小さいタイムアウト値を指定すると、TransactionScope オブジェクトに対して、後から指定した短い方のタイムアウトが適用され、スコープは指定した時間内に終了する必要があります。終了しない場合、トランザクションは自動的に中止されます。When a scope joins an ambient transaction but specifies a smaller timeout than the one the ambient transaction is set to, the new, shorter timeout is enforced on the TransactionScope object, and the scope must end within the nested time specified, or the transaction is automatically aborted. 入れ子になったスコープのタイムアウトがアンビエント トランザクションのタイムアウトより長い場合は、効果はありません。If the nested scope's timeout is more than that of the ambient transaction, it has no effect.

TransactionScope 分離レベルの設定Setting the TransactionScope isolation level

TransactionScope のオーバーロードされたコンストラクターのいくつかは、タイムアウト値の他にも、分離レベルを指定する TransactionOptions 型の構造体を受け入れます。Some of the overloaded constructors of TransactionScope accept a structure of type TransactionOptions to specify an isolation level, in addition to a timeout value. 既定では、トランザクションは Serializable に設定された分離レベルで実行されます。By default, the transaction executes with isolation level set to Serializable. Serializable 以外の分離レベルは、読み取り集中型のシステムの場合によく使用されます。Selecting an isolation level other than Serializable is commonly used for read-intensive systems. そのためには、トランザクション処理理論とトランザクション自体の動作、関連する同時実行の問題、およびシステム整合性の影響をよく理解する必要があります。This requires a solid understanding of transaction processing theory and the semantics of the transaction itself, the concurrency issues involved, and the consequences for system consistency.

さらに、すべてのリソース マネージャーがすべての分離レベルをサポートするわけではなく、構成されたレベルより高いレベルのトランザクションへの参加をリソース マネージャーが選択する場合もあります。In addition, not all resource managers support all levels of isolation, and they may elect to take part in the transaction at a higher level than the one configured.

Serializable を除くすべての分離レベルは、他のトランザクションが同じ情報にアクセスすることで生じる不整合の影響を受けやすくなっています。Every isolation level besides Serializable is susceptible to inconsistency resulting from other transactions accessing the same information. 分離レベルごとの違いは、読み取りロックおよび書き込みロックの使用方法にあります。The difference between the different isolation levels is in the way read and write locks are used. ロックには、トランザクションがリソース マネージャーのデータにアクセスするときのみ保持できるか、トランザクションがコミットまたは中止されるまで保持できるかの 2 種類があります。A lock can be held only when the transaction accesses the data in the resource manager, or it can be held until the transaction is committed or aborted. 前者はスループットの面で優れており、後者は整合性の面で優れています。The former is better for throughput, the latter for consistency. 2 種類のロックと 2 種類の操作 (読み取り/書き込み) から、4 つの基本分離レベルが構成されます。The two kinds of locks and the two kinds of operations (read/write) give four basic isolation levels. 詳細については、「IsolationLevel」を参照してください。See IsolationLevel for more information.

入れ子になった TransactionScope オブジェクトを使用する場合、入れ子になったすべてのスコープがアンビエント トランザクションに参加するときには、必ず同じ分離レベルを使用するようにそれらのスコープを構成する必要があります。When using nested TransactionScope objects, all nested scopes must be configured to use exactly the same isolation level if they want to join the ambient transaction. 入れ子になった TransactionScope オブジェクトがアンビエント トランザクションに参加するときに、別の分離レベルが指定された場合は、ArgumentException がスローされます。If a nested TransactionScope object tries to join the ambient transaction yet it specifies a different isolation level, an ArgumentException is thrown.

COM+ との相互運用Interop with COM+

新しい TransactionScope インスタンスを作成する際には、いずれかのコンストラクターで EnterpriseServicesInteropOption 列挙体を使用して、COM+ との対話方法を指定することができます。When you create a new TransactionScope instance, you can use the EnterpriseServicesInteropOption enumeration in one of the constructors to specify how to interact with COM+. 詳細については、次を参照してください。エンタープライズ サービス、および COM + トランザクションとの相互運用です。For more information on this, see Interoperability with Enterprise Services and COM+ Transactions.

参照See Also

Clone
TransactionScope