回答:
ここにコードスニペット:
using System.Transactions;
....
using (var transactionScope = new TransactionScope())
{
DoYourDapperWork();
transactionScope.Complete();
}
System.Transactions
デフォルトでは参照されないため、アセンブリへの参照を追加する必要があることに注意してください。
Dispose()
メソッドで自動的に実行します。Complete()
呼び出されていない場合、トランザクションはロールバックされます。
TransctionScope
この回答を選択する場合は、usingブロック内で接続を開く必要があります。
接続から直接トランザクションを取得することにより、より直感的なアプローチを使用することを選びました。
// This called method will get a connection, and open it if it's not yet open.
using (var connection = GetOpenConnection())
using (var transaction = connection.BeginTransaction())
{
connection.Execute(
"INSERT INTO data(Foo, Bar) values (@Foo, @Bar);", listOf5000Items, transaction);
transaction.Commit();
}
.BeginTransaction()
Execute
これは必須なので、トランザクションをパラメータとして含めるのが適切です。
TransactionScope
DapperはADO.NETコマンドだけを実行するので、使用できるはずです。
using (var scope = new TransactionScope())
{
// insert
// insert
scope.Complete();
}
すべてのテーブルが単一のデータベースにあることを考えると、私はTransactionScope
ここのいくつかの回答で提案されている解決策に同意しません。この回答を参照してください。
TransactionScope
通常、分散トランザクションに使用されます。異なるデータベースにまたがるトランザクションは、異なるシステム上にある可能性があります。これには、オペレーティングシステムとSQL Serverでいくつかの構成が必要です。この構成がないと機能しません。すべてのクエリがデータベースの単一インスタンスに対するものである場合、これは推奨されません。
ただし、単一のデータベースの場合、これは、制御できないトランザクションにコードを含める必要がある場合に役立ちます。単一のデータベースでは、特別な構成も必要ありません。
connection.BeginTransaction
単一のデータベースに対してトランザクション(C#、VB.NETなど)を実装するADO.NET構文です。これは複数のデータベースでは機能しません。
だから、connection.BeginTransaction()
行くためのより良い方法です。
トランザクションを処理するより良い方法は、この回答で説明されているようにUnitOfWorkを実装することです。
TransactionScope
OPが望むものに対して非効率的な使用を提案します。TransactionScope
多くの場合、これは優れたツールです。これではありません。
ダニエルの答えは期待通りに機能しました。完全を期すために、トランザクションスコープとdapperを使用したコミットとロールバックを示すスニペットを次に示します。
using System.Transactions;
// _sqlConnection has been opened elsewhere in preceeding code
using (var transactionScope = new TransactionScope())
{
try
{
long result = _sqlConnection.ExecuteScalar<long>(sqlString, new {Param1 = 1, Param2 = "string"});
transactionScope.Complete();
}
catch (Exception exception)
{
// Logger initialized elsewhere in code
_logger.Error(exception, $"Error encountered whilst executing SQL: {sqlString}, Message: {exception.Message}")
// re-throw to let the caller know
throw;
}
} // This is where Dispose is called
Dispose
最初に呼び出されるメソッドと2番目に呼び出されるメソッドを通信しようとはしていませんでした。「処分を2回呼び出すことは害がない」という点に関しては、それは大きな仮定です。ドキュメントと実際の実装が一致しないことがよくあることを知りました。しかし、Microsoftの言葉が必要な場合は、msdn.microsoft.com