関連付けられた SqlConnection が破棄される場合、SqlCommand.Dispose() は必要ですか?
-
05-07-2019 - |
質問
私は通常次のようなコードを使用します。
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
{
var command = connection.CreateCommand();
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
私の command
自動的に処分される?そうでなければ、それをラップする必要があります using
ブロック?処分する必要があるのか SqlCommand
?
解決
これを行うだけです:
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
コマンドでdisposeを呼び出さなくても、それほど悪いことはありません。ただし、Disposeを呼び出すと、ファイナライザへの呼び出しが抑制されます、呼び出しを破棄するとパフォーマンスが向上します。
他のヒント
最も安全なポリシーは、常に電話することです。 Dispose()
オブジェクトに実装されている場合 IDisposable
, 明示的に、または using ブロック経由で。必要ではない場合もありますが、とにかく呼び出しても問題は発生しません (クラスが正しく記述されている場合)。また、実装がいつ変更されるか、つまり以前は呼び出しが必要ではなかった場所が確実に必要になる可能性があることはわかりません。
指定した例では、接続用の外側の using ブロックを維持するだけでなく、コマンド用に追加の内側の using ブロックを追加できます。
はい、実装が現在あまり機能していない場合でも、将来どのように変更されるかはわかりません(たとえば、新しいフレームワークバージョン)。一般に、 IDisposable
を実装するすべてのオブジェクトを安全な側に配置する必要があります。
ただし、操作が延期され、完全なスコープを制御しない場合(たとえば、非同期で作業するとき、または SqlDataReader
を返すときなど)、 CommandBehaviorを設定できます。
を CloseConnection
に変更して、リーダーが完了するとすぐに接続が適切に閉じられるようにします。
Reflector またはdotPeekまたは< a href = "https://referencesource.microsoft.com/" rel = "nofollow noreferrer"> https://referencesource.microsoft.com/ 。
私は小さな掘り出しをしました(私はあなたが自分自身を掘ることをお勧めしますが、これをしっかりと試すことをお勧めしますが、私はそれを一生懸命やりませんでした)その接続に関連付けられているすべての子。さらに、実際にはコマンドの処理が実際にそのように見えるわけではありません。フィールドをnullに設定し、コンテナからデタッチし(これによりマネージメモリリークを防ぐことができます)、イベントを発生させます(これは重要かもしれませんが、誰がこのイベントをリッスンしているのかわかりません)。
どちらの方法でも、このブロックをusingブロックで使用するか、接続を保持するオブジェクトの破棄パターンを使用して破棄することをお勧めします(しばらくコマンドを保持する場合)。
実際には、破棄
をスキップできます。リソースを解放しません。 SQLCommandコンストラクターがそれを行います。
理論的には、Microsoftは実装を変更してアンマネージリソースを保持することができましたが、 Component
基本クラスを削除するよりもずっと前にAPIが登場することを願っていますそれ。
私の意見では、 SqlConnection
と SqlCommand
の両方に対して Dispose
を呼び出すことをお勧めします。以下のコードを使用してください
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();
}