5

暗黙的なロールバック (通常、例外が発生して Dispose が呼び出されたときに発生します) がすべてのプロバイダーで保証されているわけではないことを理解しました。ただし、多くの例では次を使用しています。

using (DbTransactio txn = cnctn.BeginTransaction())

その理由はありますか?

4

2 に答える 2

6

最もわかりやすい答えは、「実装されているためIDisposable」です。実装するすべてのタイプIDisposable:適切に廃棄するのはあなたの仕事です。この場合、手続き型コードを使用すると、それを行う最も簡単な方法はusingステートメントを使用することです。

この特定のケースでは、答えは次のようになります。エラーが発生した場合、トランザクションをGCに残すのではなく、ロールバックする必要があるためです。個人的には、私はおそらく慣れている傾向がありますcatchが、すでにそれを行っていることを期待Rollbackする必要があります。それが文書化されていない限り、私はそれを自分で信頼することはありません。例えば:Dispose()

using(var tran = conn.BeginTransaction()) {
    try {
        // do stuff...
        tran.Commit();
    } catch {
        tran.Rollback();
        throw;
    }
}

TransactionScopeの関連するケースでは、「Dispose()完了のマークを付けずに」がロールバックを通知するための予想される方法であることに注意してください。

using(var tran = new TransactionScope()) {
    // do stuff...
    tran.Complete();
}
于 2013-01-25T10:21:34.207 に答える
5

このようなコードがある場合:

DbTransactio txn = cnctn.BeginTransaction();

// do something which throws an exception

txn.Commit();

ガベージコレクターがトランザクションオブジェクトの収集を決定するまで、トランザクションはロールバックされません(実装するクラスがdisposeパターンIDisposableに従っている場合にのみ機能することに注意してください)。

もちろん、これを行うことができます:

DbTransaction txn = cnctn.BeginTransaction();
try
{
    // do something which throws an exception

    txn.Commit();
}
finally  
{
    txn.Dispose();
}

しかし、それはそれほど読みにくいです

using (var txn = cnctn.BeginTransaction())
{
    // do something which throws an exception

    txn.Commit();
}

編集:

暗黙的なロールバック(通常、例外が発生してDisposeが呼び出されたときに発生する)は、すべてのプロバイダーで保証されているわけではないことを理解しました。

私はそれをサポートしていない単一のプロバイダーを見たことがありません。IDbTransactionは継承するため、IDisposableすべての実装はDispose()トランザクションのロールバックに使用する必要があります。

于 2013-01-25T10:21:27.407 に答える