Language

ローカル トランザクション

ADO.NET でのトランザクションは、複数のタスクをバインドして単一の作業単位として実行する場合に使用します。 たとえば、あるアプリケーションが 2 つのタスクを実行するものとします。 まず、注文情報に従ってテーブルが更新されます。 次に、在庫情報を含むテーブルが更新され、注文された商品の数量が差し引かれます。 いずれかのタスクが失敗すると、両方の更新がロールバックされます。

トランザクションの種類の決定

トランザクションは、単一フェーズであり、データベースによって直接処理される場合、ローカル トランザクションと見なされます。 トランザクション モニターによって調整され、トランザクションの解決にフェール セーフ機構 (2 フェーズのコミットなど) が使用されているトランザクションは、分散トランザクションと見なされます。

各 .NET Framework データ プロバイダーには、ローカル トランザクションを実行するための独自の Transaction オブジェクトがあります。 SQL Server データベースでトランザクションを実行する必要がある場合は、 System.Data.SqlClient トランザクションを選択します。 Oracle トランザクションの場合は、 System.Data.OracleClient プロバイダーを使用します。 さらに、トランザクションを必要とする、プロバイダーに依存しないコードを記述するための DbTransaction クラスもあります。

注

トランザクションは、サーバー上で実行するのが最も効率的です。 明示的なトランザクションを広範に使用する SQL Server データベースを操作する場合は、Transact-SQL の BEGIN TRANSACTION ステートメントを使用して、ストアド プロシージャとしてトランザクション処理を記述するとよいでしょう。

1 つの接続を使用したトランザクションの実行

ADO.NET では、Connection オブジェクトを使用してトランザクションを制御します。 ローカル トランザクションは、BeginTransaction メソッドを使用して開始できます。 トランザクションを開始すると、Transaction オブジェクトの Command プロパティを使用して、そのトランザクションにコマンドを参加させることができます。 次に、トランザクションの内容が成功したか失敗したかに基づいて、データ ソースに対する変更をコミットまたはロールバックします。

注

EnlistDistributedTransaction メソッドをローカル トランザクションで使用することはできません。

トランザクションのスコープは、接続に限定されています。 次の例では、try ブロック内の 2 つの個別のコマンドで構成される明示的なトランザクションを実行しています。 このコマンドは、AdventureWorks SQL Server サンプル データベースの Production.ScrapReason テーブルに対して INSERT ステートメントを実行し、例外がスローされない場合、それらのステートメントはコミットされます。 catch ブロック内のコードは、例外がスローされた場合にトランザクションをロールバックします。 トランザクションが完了する前に中止されるか接続が終了すると、トランザクションは自動的にロールバックされます。

例

トランザクションを実行するには、次の手順に従います。

  1. BeginTransaction オブジェクトの SqlConnection メソッドを呼び出して、トランザクションの開始位置をマークします。 BeginTransaction メソッドは、トランザクションへの参照を返します。 この参照は、トランザクションに参加する SqlCommand オブジェクトに割り当てられます。

  2. 実行する Transaction の Transaction プロパティに、SqlCommand オブジェクトを割り当てます。 アクティブなトランザクションを持つ接続上でコマンドが実行され、Transaction オブジェクトの Transaction プロパティに Command オブジェクトが割り当てられていない場合は、例外がスローされます。

  3. 必要なコマンドを実行します。

  4. Commit オブジェクトの SqlTransaction メソッドを呼び出してトランザクションを完了するか、Rollback メソッドを呼び出してトランザクションを終了します。 Commit または Rollback メソッドが実行される前に接続が終了または破棄されると、トランザクションはロールバックされます。

次のコード例は、Microsoft SQL Server で ADO.NET を使用するトランザクション ロジックを示しています。

using (SqlConnection connection = new(connectionString))
{
    connection.Open();

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

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

    try
    {
        // Execute two separate commands.
        command.CommandText =
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
        command.ExecuteNonQuery();
        command.CommandText =
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
        command.ExecuteNonQuery();

        // Commit the transaction.
        sqlTran.Commit();
        Console.WriteLine("Both records were written to database.");
    }
    catch (Exception ex)
    {
        // Handle the exception if the transaction fails to commit.
        Console.WriteLine(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.
            Console.WriteLine(exRollback.Message);
        }
    }
}
Using connection As New SqlConnection(connectionString)
    connection.Open()

    ' Start a local transaction.
    Dim sqlTran As SqlTransaction = connection.BeginTransaction()

    ' Enlist a command in the current transaction.
    Dim command As SqlCommand = connection.CreateCommand()
    command.Transaction = sqlTran

    Try
        ' Execute two separate commands.
        command.CommandText = _
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')"
        command.ExecuteNonQuery()
        command.CommandText = _
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')"
        command.ExecuteNonQuery()

        ' Commit the transaction
        sqlTran.Commit()
        Console.WriteLine("Both records were written to database.")

    Catch ex As Exception
        ' Handle the exception if the transaction fails to commit.
        Console.WriteLine(ex.Message)

        Try
            ' Attempt to roll back the transaction.
            sqlTran.Rollback()

        Catch exRollback As Exception
            ' Throws an InvalidOperationException if the connection
            ' is closed or the transaction has already been rolled
            ' back on the server.
            Console.WriteLine(exRollback.Message)
        End Try
    End Try
End Using

こちらも参照ください