web-dev-qa-db-ja.com

関連するSqlConnectionを破棄する場合、SqlCommand.Dispose()は必要ですか?

私は通常次のようなコードを使用します:

using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
{
   var command = connection.CreateCommand();
   command.CommandText = "...";
   connection.Open();
   command.ExecuteNonQuery();
}

commandは自動的に破棄されますか?またはそうではなく、それをusingブロックにラップする必要がありますか? SqlCommandを破棄する必要がありますか?

26
abatishchev

これを行うだけです:

using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
using(var command = connection.CreateCommand())
{
   command.CommandText = "...";
   connection.Open();
   command.ExecuteNonQuery();
}

コマンドでdisposeを呼び出さなくても、それほど悪いことはありません。ただし、Disposeを呼び出すと ファイナライザーへの呼び出しが抑制されます 、disposeを呼び出すとパフォーマンスが向上します。

26
RichardOD

最も安全なポリシーは、オブジェクトがIDisposableを実装している場合、明示的にまたはusingブロックを介して、オブジェクトに対して常にDispose()を呼び出すことです。必須ではない場合もありますが、とにかく呼び出しても問題は発生しません(クラスが正しく記述されている場合)。また、実装がいつ変更されるかはわかりません。つまり、以前は呼び出しが必要でなかった場所で、今では確実に必要になります。

与えた例では、コマンド用に内側のusingブロックを追加したり、接続用の外側のusingブロックを維持したりできます。

10
Adam Ralph

はい、実装が現在あまり機能していない場合でも、将来どのように変更されるかはわかりません(たとえば、新しいフレームワークバージョン)。一般に、IDisposableを実装するすべてのオブジェクトを安全側に配置する必要があります。

ただし、操作が延期され、スコープ全体を制御できない場合(たとえば、非同期で作業する場合、またはSqlDataReaderなどを返す場合)、CommandBehaviorCloseConnectionに設定して、リーダーが完了するとすぐに接続は適切に閉じられます/破棄されます。

4
Lucero

実際には、Disposeをスキップできます。リソースを解放することはありません。 SQLCommandコンストラクターがそれを行う なので、ファイナライズも抑制しません。

理論的には、Microsoftはアンマネージリソースを保持するように実装を変更できますが、それを行うずっと前にComponent基本クラスを削除するAPIが提供されることを願っています。

2
Edward Brey

この種のものは、 Reflector またはdotPeekまたは https://referencesource.Microsoft.com/ を使用して見つけることができます。

私は小さな掘り出し物を持っていました(私はそれを一生懸命試みなかったので、これの残りを完全に確信するためにあなた自身を掘ることをお勧めします)そしてあなたが接続を殺すとき関連する子供たちの処分がないように見えますその接続で。さらに、コマンドの破棄が実際にそれほど多くのことを行うようには見えません。フィールドをnullに設定し、コンテナーから切り離して(これにより、マネージメモリリークを防ぐことができます)、イベントを発生させます(これは重要かもしれませんが、誰がこのイベントをリッスンしているかわかりません)。

いずれにせよ、usingブロックでこのようなものを使用するか、接続を保持するオブジェクトのdisposeパターンを使用して確実に破棄することをお勧めします(コマンドをしばらく保持する場合)。

2
Quibblesome

私の意見では、DisposeSqlConnectionの両方に対してSqlCommandを呼び出すことは良い習慣です、以下のコードを使用してください

using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
try{
    using(var command = connection.CreateCommand())
    {
       command.CommandText = "...";
       connection.Open();
       command.ExecuteNonQuery();
    }
}
catch(Exception ex){ //Log exception according to your own way
    throw;
}
finally{
    command.Dispose();
    connection.Close();
    connection.Dispose();
}
1
Tahir Alvi