web-dev-qa-db-ja.com

dapper.netでトランザクションを使用するには?

複数のテーブルで複数の挿入ステートメントを実行したいと思います。私はdapper.netを使用しています。 dapper.netでトランザクションを処理する方法がわかりません。

Dapper.netでトランザクションを使用する方法に関するアイデアを共有してください。

96
Amit

コードスニペットは次のとおりです。

using System.Transactions;    
....    
using (var transactionScope = new TransactionScope())
{
    DoYourDapperWork();
    transactionScope.Complete();
}

デフォルトでは参照されないため、System.Transactionsアセンブリへの参照を追加する必要があることに注意してください。

93
the_joric

接続から直接トランザクションを取得することにより、より直感的なアプローチを使用することを好みました。

// 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();
}
87
ANeves

DapperはADO.NETコマンドのみを実行するため、TransactionScopeを使用できるはずです。

using (var scope = new TransactionScope())
{
   // insert
   // insert
   scope.Complete();
}
18
Daniel A. White

すべてのテーブルが単一のデータベースにあることを考慮すると、ここのいくつかの回答で提案されたTransactionScopeソリューションに同意しません。 this answerを参照してください。

  1. TransactionScopeは一般に分散トランザクションに使用されます。異なるデータベースにまたがるトランザクションは、異なるシステム上にある場合があります。これには、オペレーティングシステムとSQL Serverのいくつかの構成が必要です。これがないと機能しません。すべてのクエリがデータベースの単一インスタンスに対して行われる場合、これは推奨されません。
    しかし、単一のデータベースでは、これは、制御下にないコードをトランザクションに含める必要がある場合に役立ちます。単一のデータベースでは、特別な構成も必要ありません。

  2. _connection.BeginTransaction_は、単一のデータベースに対してトランザクション(C#、VB.NETなど)を実装するADO.NET構文です。これは複数のデータベースでは機能しません。

したがって、connection.BeginTransaction()を使用する方が適切です。

this answerで説明されているように、トランザクションを処理するより良い方法はUnitOfWorkを実装することです。

6
Amit Joshi

ダニエルの答えは期待どおりに機能しました。完全を期すために、トランザクションスコープと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 
4