web-dev-qa-db-ja.com

Dapper.IDbConnectionでBeginTransactionを使用する適切な方法

DapperでBeginTransaction()IDbConnectionとともに使用する適切な方法はどれですか?

BeginTransaction()を使用する必要があるメソッドを作成しました。これがコードです。

_using (IDbConnection cn = DBConnection)
{
    var oTransaction = cn.BeginTransaction();

    try
    {
        // SAVE BASIC CONSULT DETAIL
        var oPara = new DynamicParameters();
        oPara.Add("@PatientID", iPatientID, dbType: DbType.Int32);
        ..........blah......blah............
    }
    catch (Exception ex)
    {
        oTransaction.Rollback();
        return new SaveResponse { Success = false, ResponseString = ex.Message };
    }
}
_

上記のメソッドを実行すると-例外が発生しました-

操作が無効です。接続が閉じられます。

これは、接続が開かれる前にトランザクションを開始できないためです。したがって、次の行を追加すると、cn.Open();、エラーが解決されます。しかし、私はどこかで手動で接続を開くことを読んだことがあります悪い習慣!! Dapperは必要なときだけ接続を開きます。

Entityフレームワークでは、TransactionScopeを使用してトランザクションを処理できます。

したがって、私の質問は、Dapperの行cn.Open()...を追加せずにトランザクションを処理するための良い方法は何ですか?これには適切な方法があるはずです。

25
Krishnraj Rana

電話しないでください

cn.Close();

usingブロックも閉じようとするためです。トランザクション部分については、はい、TransactionScopeもEntity Framework関連の手法ではないため、同様に使用できます。これを見てくださいSO answer: https://stackoverflow.com/a/6874617/566608 トランザクションスコープに接続を登録する方法を説明しています。重要な側面は次のとおりです。接続は、スコープ内で接続を開くトランザクションIIFに自動的に登録されます

6
Felice Pollano

Tim Schreiber ソリューションを見てください。これはシンプルでありながら強力で、リポジトリパターンを使用して実装され、_Dapper Transactions_を念頭に置いています。

以下のコードのCommit()はそれを示しています。

_public class UnitOfWork : IUnitOfWork
{
    private IDbConnection _connection;
    private IDbTransaction _transaction;
    private IBreedRepository _breedRepository;
    private ICatRepository _catRepository;
    private bool _disposed;

    public UnitOfWork(string connectionString)
    {
        _connection = new SqlConnection(connectionString);
        _connection.Open();
        _transaction = _connection.BeginTransaction();
    }

    public IBreedRepository BreedRepository
    {
        get { return _breedRepository ?? (_breedRepository = new BreedRepository(_transaction)); }
    }

    public ICatRepository CatRepository
    {
        get { return _catRepository ?? (_catRepository = new CatRepository(_transaction)); }
    }

    public void Commit()
    {
        try
        {
            _transaction.Commit();
        }
        catch
        {
            _transaction.Rollback();
            throw;
        }
        finally
        {
            _transaction.Dispose();
            _transaction = _connection.BeginTransaction();
            resetRepositories();
        }
    }

    private void resetRepositories()
    {
        _breedRepository = null;
        _catRepository = null;
    }

    public void Dispose()
    {
        dispose(true);
        GC.SuppressFinalize(this);
    }

    private void dispose(bool disposing)
    {
        if (!_disposed)
        {
            if(disposing)
            {
                if (_transaction != null)
                {
                    _transaction.Dispose();
                    _transaction = null;
                }
                if(_connection != null)
                {
                    _connection.Dispose();
                    _connection = null;
                }
            }
            _disposed = true;
        }
    }

    ~UnitOfWork()
    {
        dispose(false);
    }
}
_
3
vaheeds

このUowパターンを実装しましたが、非同期呼び出しに問題があります。時々_transaction.Dispose()で受信する接続はMultipleActiveResultSetsをサポートしていません。

0
user1770849