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