スレッドを読んだことSqlCommand.Disposeで十分ですか?そして閉会と廃棄WCFサービスであれば、私は近くのDisposeむしろ閉じるよりも、私は、このようなSqlConnectionオブジェクトまたはStreamクラスから継承するいくつかのクラスの一つとしてクラスについて疑問に思って、それは問題ではありませんか?
スレッドを読んだことSqlCommand.Disposeで十分ですか?そして閉会と廃棄WCFサービスであれば、私は近くのDisposeむしろ閉じるよりも、私は、このようなSqlConnectionオブジェクトまたはStreamクラスから継承するいくつかのクラスの一つとしてクラスについて疑問に思って、それは問題ではありませんか?
回答:
MicrosoftのガイドラインによるとClose、適切な場所にメソッドを提供することは良い習慣です。ここからの引用であるフレームワークの設計ガイドラインは、
その地域の標準的な用語が近い場合は
Close()、に加えてメソッドを提供することを検討してくださいDispose()。その際、Close実装を同じにすることが重要Disposeです...
ほとんどの場合Close、Disposeメソッドとメソッドは同等です。主な違いの間CloseとDisposeする場合にはSqlConnectionObject次のとおりです。
アプリケーションは
Close複数回呼び出すことができます。例外は生成されません。
Disposeメソッド を呼び出すと、SqlConnectionオブジェクトの状態がリセットされます。破棄されたSqlConnectionオブジェクトでメソッドを呼び出そうとすると、例外が発生します。
それは言った:
Dispose。Closeメソッドを使用します。con.Open() con.Close(); 2 con.Open(); // reuse 3. con.Dispose(); // use one time con.Open(); // error
いつものように、答えは次のとおりです。異なるクラスIDisposableは異なる方法で実装され、必要な研究を行うのはあなた次第です。
限りでSqlClientは、次のことをお勧めします。
using (SqlConnection conn = /* Create new instance using your favorite method */)
{
conn.Open();
using (SqlCommand command = /* Create new instance using your favorite method */)
{
// Do work
}
conn.Close(); // Optional
}
あなたは必要があります呼び出すことDispose(またはClose接続に*)!んではない、これは(少なくとも)次のGCサイクルまでプール内の接続をタイアップされます、あなたの接続をクリーンアップするガベージコレクタを待ちます。を呼び出す場合、を呼び出すDispose必要はありませんClose。また、using構成によってDispose正しく処理するのが非常に簡単になるため、を呼び出す理由はまったくありませんClose。
接続は自動的にプールされ、接続でDispose/ を呼び出しCloseても、接続は物理的には閉じられません(通常の状況)。独自のプーリングを実装しないでください。 SqlClient(データベースコンテキストと接続オプションの復元のように)接続がプールから取得されたときに、接続に対してクリーンアップを実行します。
*を呼び出す場合Closeは、例外に対して安全な方法(つまり、catchまたはfinallyブロック)で実行してください。
conn.Close(); // Optionalそれはオプションではありません。冗長で不要です。オブジェクトを2回破棄すると、一部のコード分析ツールによって警告としてマークされます。
using (var x = ..) { x.Dispose(); }この場合、x実際には「2回破棄」されます。
Dispose()を呼び出す必要があります!
Dispose()は開発者が呼び出すためのもので、ガベージコレクターはFinalize()を呼び出します。オブジェクトでDispose()を呼び出さない場合、ガベージコレクターが近づき、finalizeを呼び出すまで、オブジェクトで使用されていたアンマネージリソースは破棄されません(誰がいつ発生するかがわかります)。
このシナリオは非確定的ファイナライズと呼ばれ、.net開発者にとって一般的な罠です。IDisposableを実装するオブジェクトを使用している場合は、それらに対してDispose()を呼び出します。
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
いくつかのオブジェクトでDisponse()を呼び出し、その接続でClose()を呼び出すか、ファイルハンドルを閉じるだけの多くのインスタンス(SqlConnectionなど)があるかもしれませんが、ほとんどの場合、Dispose()を呼び出すのが最善です。非常に近い将来にオブジェクトを再利用する予定がない限り。
Dispose。
Dispose() using()IDisposableusing()Dispose()Close()Open()
Close接続、Postgresは自動的に接続識別子を設定しますnull。それ以降、Disposeすでにに設定されているSQL接続識別子は使用できませんnull。
のためSqlConnection、接続自体の観点からは、これらは同等です。Reflectorによると、ほとんどのメンバーをnullに設定することにより、Dispose()呼び出しClose()と、いくつかの追加のメモリ解放操作を実行します。
ストリームの場合、それらは実際には同等です。 Stream.Dispose()単にClose()を呼び出します。
Componentものであり、呼び出しを試みても何もしないようですClose()。私は、内のどこにでも見ることができないDBConnectionか、SqlConnectionこれらの通知のいずれかにネクタイという。ただし、DisposeMe()どこにも参照されないプライベートがあります。
この迅速なアドバイスは長い答えになりました。ごめんなさい。
タイラーが彼の素晴らしい答えで指摘したように、電話Dispose()は素晴らしいプログラミングの実践です。これは、このメソッドは必要なすべてのリソース解放を「まとめて」行うことになっているため、不要なオープンリソースがないためです。たとえば、テキストをファイルに書き込んで、ファイルを閉じる(リソースを解放する)のに失敗した場合、そのファイルは開いたままになり、GCが出て、必要な処理を行うまで、他のユーザーはそのファイルに書き込むことができません。完了しました。
さて、場合によってはStreamWriter.Close()、をオーバーライドするような、処理しているクラスに固有の「ファイナライズ」メソッドがあるでしょうTextWriter.Close()。実際、これらは通常、状況により適しています。Close()たとえば、StreamWriter Dispose()は、オブジェクトを処理する前にストリームと基になるエンコーダーをフラッシュします。涼しい!
ただし、MSDNを参照すると、Microsoftでさえ、多くのクローザーとディスポーザーに混乱していることがあります。このウェブページでは、たとえば、いくつかの例でClose()は暗黙の前に呼び出されDispose()(暗黙の理由がわからない場合は、usingステートメントを参照してください)、特に、それらは気にしません。なぜでしょうか?私も困惑しました。
私が考えた理由(そして、私は強調しますが、これは元の研究であり、私が間違っていると確かに評判を失う可能性があります)はClose()失敗する可能性があり、リソースを開いたままにすると例外が発生し、リソースDispose()は確実に解放されます。これがが常にコールを保護するDispose()必要Close()がある理由です(しゃれのために申し訳ありません)。
MyResource r = new MyResource();
try {
r.Write(new Whatever());
r.Close()
finally {
r.Dispose();
}
そして、はい、Microsoftはその1つの例で失敗したと思います。おそらく、そのタイムスタンプはファイルにフラッシュされません。
明日、古いコードを修正します。
編集:申し訳ありません、ブラノン、私はあなたの答えにコメントすることはできませんがClose()、finallyブロックを呼び出すことは良い考えですか?それからの例外は、ブロックの残りを台無しにするかもしれないと思います、それはおそらく重要なクリーンアップコードを含むでしょう。
Brannon'sへの返信:すばらしい。Close()本当に必要なときに呼び出すことを忘れないでください(たとえば、ストリームを処理するとき-.NETでのSQL接続についてはあまり知らない)。
iDisposableに型キャストし、その上でdisposeを呼び出します。これにより、関数の名前に関係なく、「iDisposable.Dispose」を実装するように構成されているメソッドが呼び出されます。
IDisposable.Dispose、それがその名前であるとは限りません。vb.netでは、関数をその関数の名前と関連付ける必要のない名前を持つ複数のインターフェイスメンバーにバインドすることが可能であることに注意してください。
using (myObj as IDisposable)
一般に、Close()、Abort()、Dispose()の問題に直面していますが、それらの違いについて説明します。
1)中止:-中止が呼び出されると、クライアントはサーバーに通知せずに接続を削除し、サーバーが一定時間(約1分)待機するため、これを使用することはお勧めしません。バルクリクエストがある場合、限られた接続プールでタイムアウトが発生する可能性があるため、abort()を使用できません。
2)閉じる:-接続を閉じるときにサーバーを呼び出し、サーバーがその側で閉じることを確認するため、接続を閉じるには非常に良い方法です。
ここで、もう1つ見てみましょう。場合によっては、エラーが発生したときに、そのconnection.close()にコードを書き込むのは適切な方法ではありません。その時点で通信状態に障害が発生するためです。
3)破棄:-これは一種のクローズですが、接続を閉じた後は、再度開くことはできません。
このようにしてみてください、
private void CloseConnection(Client client)
{
if (client != null && client.State == CommunicationState.Opened)
{
client.Close();
}
else
{
client.Abort();
}
}
client != nullは、すべての使用を保護するわけではないため、誤り/誤解を招くものです。また、コードがどのようにして「この接続は開かれておらず、閉じる必要がある」という状態になるのかわかりません。