52

コードで使用している 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;
}

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

4

8 に答える 8

62

ブロックのスコープ内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()呼び出し中にそれらのメンバーを破棄する必要があることに注意してください。

于 2009-07-14T20:30:21.547 に答える
30

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

于 2009-07-14T20:32:18.767 に答える
16

基本的に、usingは、すべての例外をキャッチする代わりにintをfinallyブロックすることを除いて、実行しているのと同じことを行います。

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

と同じですが、コードははるかに少ないです:)

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

               //some code
               tr.Commit();
            }
            finally
            {
                if(tr != null && tr is IDisposable)
                {
                    tr.Dispose();
                }
            }
        }
    }
    finally
    {
        if(cn != null && cn is IDisposable)
        {
            cn.Dispose();
        }
    }
}
于 2009-07-14T20:35:44.157 に答える
9

結局のところ、usingはパターンのショートカットにすぎません。ただし、パターンを正しく実装し、少ないコードで実装できるため、非常に便利で便利なショートカットです。

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

于 2009-07-14T20:34:22.663 に答える
4

usingステートメントは、接続とトランザクションを閉じて破棄します。これは、破棄を行う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();
}
于 2009-07-14T20:32:24.710 に答える
3

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

于 2009-07-14T20:31:03.200 に答える
1

コードが返された後に接続オブジェクトが破棄されることを保証します。Dispose は、管理対象外のリソースを解放するのに便利です。オブジェクトが IDisposable を実装している場合、常に dispose メソッドを呼び出すことをお勧めします。

于 2009-07-14T20:40:33.710 に答える
1

それに加えて、コードをきれいにします。7 行のコードは 14 行よりも見栄えがよくありませんか? 使用中のブロックを見るたびに安堵の兆しを見せます。それは、あのうれしそうな臭いから出てくる小さな霧のようなものです。うーん、私は効率的なコードのかなりのブロックです。私がどれだけ記憶を管理しているか、そして私がどれだけ目を楽しませているか見てください。

于 2012-04-06T16:51:03.593 に答える