web-dev-qa-db-ja.com

SqlTransactionでusingステートメントを使用する理由

私は自分のコードで使用しているSqlTransactionに関するいくつかの問題に直面しています。グーグルで調べている間に、SqlTransactionでusingステートメントを使用している人がたくさんいます。

このタイプのステートメントをSqlTransactionで使用することの利点および/または違いは何ですか?

using (SqlConnection cn = new SqlConnection())
{
     using (SqlTransaction tr = cn.BeginTransaction())
     {
      //some code
      tr.Commit();
     }
}

現在、私のコードは次のようになっています。

SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"]);
cn.Open();
SqlTransaction tr = cn.BeginTransaction();

try
{
     //some code
     tr.Commit();
     cn.Close();
}
catch(Exception ex)
{
      tr.Rollback();
      cn.Close();
      throw ex;
}

ある方法が他の方法より優れている点は何ですか?

47
MDStephens

usingブロックのスコープ内を実装するクラスのインスタンスを作成するたびに、IDisposableステートメントを使用する必要があります。例外がスローされるかどうかに関係なく、そのインスタンスでDispose()メソッドが確実に呼び出されます。

特に、コードはマネージ例外のみをキャッチし、既存の例外を再スローする代わりに新しい例外をスローすることでスタックフレームを破棄します。

正しい方法は次のとおりです。

_using (SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"])) {
    cn.Open();
    using (SqlTransaction tr = cn.BeginTransaction()) {
        //some code
        tr.Commit();
    }
}
_

クラスにIDisposableを実装する型のインスタンスメンバーがある場合、クラスはIDisposable自体を実装し、独自のDispose()呼び出し中にそれらのメンバーを破棄する必要があることに注意してください。

57
John Saunders

これは、SqlTransactionオブジェクトが明示的にコミットされなかった場合(例外がスローされた場合など)に、Dispose()メソッドでロールバックするためです。つまり、コードと同じ効果があり、ほんの少しだけきれいになります。

26
Ken Keenan

結局、usingは単なるパターンのショートカットです。しかし、これは非常に有用なであり、便利なショートカットです。パターンを正しく実装し、より少ないコードで実行できることを意味するためです。

この場合、パターンを正しく実装していません。 tr.RollBack()への呼び出しも例外をスローした場合、コードはどうなりますか?

6
Joel Coehoorn

sing文 は、接続とトランザクションを閉じて破棄します。破棄を行うtry/catchにfinallyブロックを設定するのと同じです。

また、このように使用ブロックを少し圧縮することもできます...

using (SqlConnection cn = new SqlConnection())
using (SqlTransaction tr = cn.BeginTransaction())     
{
      //some code
      tr.Commit();
}

これは次とほぼ同じです。

SqlConnection cn = null;
SqlTransaction tr = null;
try
{
    cn = new SqlConnection());
    tr = cn.BeginTransaction());

    //some code
    tr.Commit();
}
finally
{
    if (cn != null)
        cn.Dispose();
    if (tr != null)    
        tr.Dispose();
}
4
Scott Ivey

Using()ブロックを使用しない場合、SqlConnectionおよびSqlTransactionオブジェクトの.Dispose()メソッドを明示的に呼び出す必要があります。そうしないと、管理されていないリソースは解放されず、メモリリークやその他の問題が発生する可能性があります。

3
Matthew Groves

それに加えて、コードをきれいにします。 7行のコードは、14行よりも見栄えがよくありませんか?使用ブロックを見るたびに、私は安心のサインを吸います。それはそのうれしい臭いものから出てくる霧の小さな噴出のようなものです。うーん、私はかなり効率的なコードのブロックです。私がどれほどうまくメモリを管理しているか、そして私がどれほど楽しいかを見てください。

2
Levitikon

を使用して、コードが戻った後に接続オブジェクトが破棄されることを保証します。 Disposeは、管理されていないリソースを解放するのに役立ちます。グッドプラクティスとして、オブジェクトがIDisposableを実装する場合、disposeメソッドを常に呼び出す必要があります。

1
jyotishka bora

Usingステートメントは、リソースを適切に処理するための略記です。詳細については、 ステートメントの使用に関するMSDN記事 を参照してください。

0
pdwetz