5

SqlConnection を使用する場合は、.Close() を使用するか、SqlConnection を "using" に配置することにより、使用時に常に閉じることが重要です。残念ながら、私を含む人々はそれを忘れがちであり、接続を閉じるのを何度も忘れるか、アプリケーションを使用する人の数が増えるまで、ガベージコレクターがしばらくの間私を救ってくれます.

可能であれば、ガベージ コレクターが SqlConnection を破棄したかどうかを検出する方法を知りたいです。

もう 1 つの方法は、SqlConnection を継承し、その初期化子にタイマーを設定して、クラスを破棄するときに接続が閉じられるまでにかかった時間を確認することです。私はタイマーがあまり好きではありませんが、これを書いているときにアイデアが思い浮かびました。

たぶん、これらすべてに対する 3 番目のさらにスマートな方法があると思います...どの方法をお勧めしますか?

4

6 に答える 6

4

SqlConnection は封印されているため、継承することはできません。(そして、そうするのは良い考えではないと思います-可能であれば、おそらくコードをDispose(false)に追加する必要があります。これは、ファイナライザーが呼び出すものだからです)。

この種の問題は、静的コード分析ツールを使用して検出することをお勧めします。このツールには、コード内で接続を破棄するのを忘れたすべての場所を検出する機能があります。Visual Studioに組み込まれているもの、またはFxCopを使用できます。

接続の破棄を忘れないようにするために、次のことをお勧めします。

  • すべての DB 接続コードを 1 つのレイヤー / アセンブリ / モジュールに保持して、プロジェクトに分散しないようにします。
  • SQL コマンドを実行して結果を返すためのユーティリティ メソッドがあります。そのため、必要以上に SQLConnection を作成しないでください。
  • C# using construct を使用することを忘れないでください。
于 2010-06-29T18:25:23.253 に答える
2

経験則によると、「ガベージコレクターについて考える必要がある場合は、おそらく何か間違ったことをしている」とのことです。(もちろん、他の親指もあります...)

接続が明示的に、またはブロックを介して閉じられていることを確認することが最善のルートusingであるように思われます。finally

明らかに、あなたはすでにこれらのテクニックを理解しています...したがって、おそらくコードを1回実行し、可能なリファクタリングで十分です。

于 2010-06-29T18:23:54.060 に答える
1

アプリケーションが SQL 接続プール (デフォルト) を使用している場合、.Close() を呼び出したり、using() {} ブロックを離れたりしても接続が再利用され、閉じられないため問題ありません。

http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

あなたの質問に答えるために、GCコレクションのイベントがあるとは思いませんが、GCがそのコレクションパスでオブジェクトをリサイクルすることを選択したかどうかがわからないため、あったかどうかは問題ではありません(すべてのオブジェクトがクリーンアップされるわけではありません世代アルゴリズム)。

また、オブジェクトへの参照を保持し、破棄されないようにする可能性があるため、タイマーと「チェック」を使用しようとする試みも避けます。

于 2010-06-29T18:25:52.677 に答える
1

私はガベージコレクターにあまり詳しくなく、情報を直接取得する方法があるかどうかはわかりませんが、最初のアイデアは次のとおりです。

ダミー オブジェクトへの弱参照を作成するだけです。後で弱参照を見て、オブジェクトがもう生きていない場合は、おそらくガベージ コレクションが発生したと推測できます。

(この回答は、ガベージ コレクターの実行の検出にのみ適用されます。これを行う理由を完全に無視しました。リソース リークに対処するためのより良い戦略があります。)

于 2010-06-29T18:27:43.973 に答える
0

破棄するのを忘れた場合、オブジェクトは完成します。これが発生する時間を制御する方法はありません。また、オブジェクトがファイナライズされているかどうかを知る方法もありません。オブジェクトをファイナライズするには、別のスレッドを作成する必要があるため、アプリケーションの速度が低下します。だからあなたは処分したいのです。IDisposableを実装するフレームワークのすべてのクラスで、GC.SuppressFinalizeが呼び出されるため、オブジェクトはファイナライズされません。

この動作を制御する方法はありません。オブジェクトが使用されなくなった場合、オブジェクトは自動的に収集されます。これを止めるためにできることは、GC.SuppressFinalizeを呼び出すことだけですが、それを忘れると、一生ねじ込まれてしまうので、お勧めしません。

ただし、(子クラスではなく)ラッパークラスを作成して、常にDisposeを呼び出すいくつかの単純なメソッドを提供するコードで使用することができます。それ以外の場合は、よく確認してください。

于 2010-06-29T18:24:35.133 に答える
0

まず、GC の使用を検討している場合でも、どこかに深刻な問題があります。コードで Close が確実に呼び出されるようにする最善の方法は、モックなどの手法を使用してコードを単体テストすることです。単体テストで Close が呼び出されたことが示されている場合、コードは正しく、ガベージ コレクターをいじるなどの不必要に危険なことを行う必要はありません。

第 2 に、それでもランタイム チェック ルートを使用することを主張する場合、考慮すべき唯一のことはStateChangeSqlConnection. たとえば、ConnectionState が Open から Closed に変更された場合に発生します。

于 2010-06-29T18:27:43.197 に答える