SqlConnectionsをDispose()しないことはどれほど悪いですか?


14

個人的には、usingステートメントにIDisposableを実装するADOオブジェクトを配置しないと、ハイブが発生します。しかし、私の現在の契約では、自社開発のエンタープライズフレームワークの「データアクセスプロバイダー」コードは、1)IDisposableを実装せず、2)使用するあらゆるものに対してDispose()をいつでも呼び出さないことがわかりました。ユーザーは、このフレームワークをデータアクセスに頻繁に使用するWinformsアプリケーションのパフォーマンスの問題について多くの不満を述べています。また、コードにはパフォーマンスに影響を与える可能性のある他の問題がたくさんありますが、他よりも垂れ下がった果物。

だから、「廃棄するのは理由があるのでそれを使う」といったことを言う以外に、これらの人々に、これが本当に、本当に悪いと納得させるように言うことができますか?


5
私の推測では、ある時点で説得力は必要ではないということです:)
ハンニバルレクター博士

回答:


6

あなたができる最善のことは、Dispose() ここでのマイクロソフトのパターンと実践を彼らに示すことだと思います。彼らの目の前にあるこのツールを利用しないことの完全な結果を彼らに見せてください。


1
一番上に「これは廃止されたコンテンツです」と叫ぶことのないバージョンが見つかることを願っています。
AJジョンソン

ご存知のように、私の目はちょうどそれについて光沢がありました。しかし、今それを注意深く読んで、私は人々がそのページから引退する「まだ使用している」かもしれない技術を疑問に思います。たぶんCAS?
ジェシーC.スライサー

もっと綿密に調べてみると、これの大部分はまだ私に関係があるようです。なぜ廃止されたのかわからない。
AJジョンソン

10

SQL接続でDisposeメソッドを呼び出さない場合、使用後にその接続は接続プールに戻されません。

パフォーマンスの問題がある場合、私の推測では、データベース上で最大の接続が開かれています。DBAはこれを簡単に確認できます。

Microsoftのベストプラクティスでは、接続コードをUsingステートメント内に配置し、接続が破棄され、接続がプールに戻されるようにします。


呼び出しCloseは、接続プールに戻るために十分です。質問Closeは、明示的に使用されていないことを述べていません。
user2864740

9

データベース接続プールのサイズには制限があり、いっぱいになると、新しい接続は古い接続が解放されるのを待ちます。それらを使い終わったらすぐに処分しないと、ファイナライザーの実行時に最終的に解放されますが、それは将来の不確定な時間です...だからせいぜい、あなたは新しい接続を開くときに長い遅延が発生します。

最悪の場合、接続プールが無効になっている可能性があります。おそらく、しばらくして、アプリが「接続を待機しているタイムアウト」エラーを返し、接続プールを無効にするとその問題が「解決」したことを発見したのでしょう。しかし、これは毎回まったく新しい接続を作成していることを意味するため、はるかに悪いです-これは驚くほどリソースを消費します。データベースへの何百もの接続を開いている場合、パフォーマンスの問題が発生しているのも不思議ではありません。

これらの問題をすべて解決する正しい方法は、接続が終了したらすぐに破棄することです。最良のアイデアは、必要なだけ接続を開いたままにしておくことです。


1
これよりも少し悪いです。プールが十分にバックアップされると、管理ツールからの接続試行を含め、最終的に多くの接続試行が失敗するだけであり、データベースの自分自身を効果的にロックできます。
ジョエルCoehoorn 14

3

深刻なアプリケーションでは、それはかなり悪いと言えます。これらのオブジェクトは、キルパフォーマンスの周りに浮かんでいるだけでなく、単にプロフェッショナルではありません。幸いなことに、Microsoftはオブジェクト階層にFinalizeを実装しています。

~Object()
{
    this.Dispose(false);    
}

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    // ...
}

取る System.Data.SqlClient.SqlConnection例えば:

System.ComponentModel.Component  <-Finalize disposeパターンを実装します。
    |
System.Data.Common.DbConnection
    |
System.Data.SqlClient.SqlConnection

オブジェクトは最終的に破棄されますが、非決定論的な性質によりパフォーマンスが大きく損なわれます。


0

まあ、1つには、接続を終了していません。そのため、a)自動的にドロップするか、b)クライアントが使用しなくても循環して更新する必要があります。

b)あなたが説明しているパフォーマンスヒットのためだと思います。ただし、それが唯一の理由ではない可能性があります。

できればクライアント側で接続を閉じる必要がありますが、サーバー側でもフェールセーフを実装する必要があります。それ以外の場合は、データベースサーバーがgod-knows-whenでリリースされるまで処理する必要があるという余分ながらくたがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.