暗黙的なロールバック (通常、例外が発生して Dispose が呼び出されたときに発生します) がすべてのプロバイダーで保証されているわけではないことを理解しました。ただし、多くの例では次を使用しています。
using (DbTransactio txn = cnctn.BeginTransaction())
その理由はありますか?
暗黙的なロールバック (通常、例外が発生して Dispose が呼び出されたときに発生します) がすべてのプロバイダーで保証されているわけではないことを理解しました。ただし、多くの例では次を使用しています。
using (DbTransactio txn = cnctn.BeginTransaction())
その理由はありますか?
最もわかりやすい答えは、「実装されているため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();
}
このようなコードがある場合:
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()
トランザクションのロールバックに使用する必要があります。