ローカル トランザクション
ADO.NET でのトランザクションは、複数のタスクをバインドして単一の作業単位として実行する場合に使用します。 たとえば、あるアプリケーションが 2 つのタスクを実行するものとします。 まず、注文情報に従ってテーブルが更新されます。 次に、在庫情報を含むテーブルが更新され、注文品の金額が借方記入されます。 いずれかのタスクが失敗すると、両方の更新がロールバックされます。
トランザクションの種類の判別
トランザクションは、単一フェーズであり、データベースによって直接処理される場合、ローカル トランザクションと見なされます。 トランザクション モニターによって調整され、トランザクションの解決にフェール セーフ機構 (2 フェーズのコミットなど) が使用されているトランザクションは、分散トランザクションと見なされます。
各 .NET Framework データ プロバイダーには、ローカル トランザクションを実行するための独自の Transaction
オブジェクトがあります。 トランザクションを SQL Server データベースで実行できるようにする場合は、System.Data.SqlClient トランザクションを選択します。 Oracle トランザクションの場合は、System.Data.OracleClient プロバイダーを使用します。 さらに、トランザクションを必要とする、プロバイダーに依存しないコードを記述するための DbTransaction クラスもあります。
Note
トランザクションは、サーバー上で実行するのが最も効率的です。 明示的なトランザクションを広範に使用する SQL Server データベースを操作する場合は、Transact-SQL の BEGIN TRANSACTION ステートメントを使用して、ストアド プロシージャとしてトランザクション処理を記述するとよいでしょう。
単一の接続を使用したトランザクションの実行
ADO.NET では、Connection
オブジェクトを使用してトランザクションを制御します。 ローカル トランザクションは、BeginTransaction
メソッドを使用して開始できます。 トランザクションを開始すると、Transaction
オブジェクトの Command
プロパティを使用して、そのトランザクションにコマンドを参加させることができます。 次に、トランザクションの内容が成功したか失敗したかに基づいて、データ ソースに対する変更をコミットまたはロールバックします。
Note
EnlistDistributedTransaction
メソッドをローカル トランザクションで使用することはできません。
トランザクションのスコープは、接続に限定されています。 次の例では、try
ブロック内の 2 つの個別のコマンドで構成される明示的なトランザクションを実行しています。 これらのコマンドでは、SQL Server の AdventureWorks サンプル データベース内の Production.ScrapReason テーブルに対して INSERT ステートメントが実行され、例外がスローされない場合はコミットされます。 catch
ブロック内のコードは、例外がスローされた場合にトランザクションをロールバックします。 トランザクションが完了する前に中止されるか接続が終了すると、トランザクションは自動的にロールバックされます。
例
トランザクションを実行するには、次の手順に従います。
BeginTransaction オブジェクトの SqlConnection メソッドを呼び出して、トランザクションの開始位置をマークします。 BeginTransaction メソッドは、トランザクションへの参照を返します。 この参照は、トランザクションに参加する SqlCommand オブジェクトに割り当てられます。
実行する
Transaction
の Transaction プロパティに、SqlCommand オブジェクトを割り当てます。 アクティブなトランザクションを持つ接続上でコマンドが実行され、Transaction
オブジェクトのTransaction
プロパティにCommand
オブジェクトが割り当てられていない場合は、例外がスローされます。必要なコマンドを実行します。
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