8

.NETのSqlConnectionクラスを使用してSQLServerデータベースと通信するクライアントコードがいくつかあります。このエラーで断続的に失敗しています:

「ExecuteReaderには、開いていて利用可能な接続が必要です。接続の現在の状態は閉じています。」

「一時的な」解決策は、プロセスを再起動することです。その後、すべてが機能しますが、それは明らかに不十分です。

コードは、データベースごとに1つずつ、SqlConnectionインスタンスのキャッシュを保持しています。

コードを書き直したいのですが、その前に、いくつかのことを知っておく必要があります。

私の最初の質問は次のとおりです。SqlConnectionオブジェクトを繰り返し接続および切断するのは非効率的ですか、それとも基盤となるライブラリが私たちに代わって接続プールを実行しますか?

// Is this bad/inefficient?
for(many-times)
{
    using(SQLConnection conn = new SQLConnection(connectionString))
    {
        // do stuff with conn
    }
}

私たちのコードは上記を行わないため、問題の原因として考えられるのは、接続の「存続期間」中に基盤となるSQLServerデータベースに何かが発生し、接続が閉じられることです。

SqlConnectionオブジェクトを「キャッシュ」する価値があることが判明した場合、データベースに「再接続」するだけで解決できるすべてのエラーを処理するための推奨される方法は何ですか。私は次のようなシナリオについて話している:

  • データベースがオフラインになり、オンラインに戻りますが、これが発生している間、クライアントプロセスには開いているトランザクションがありませんでした
  • データベースは「切断」され、次に「再接続」されました

SqlConnectionに「State」プロパティがあることに気付きました...それを照会する適切な方法はありますか?

最後に、完全なアクセス権でセットアップされたテストSQLServerインスタンスがあります。「ExecuteReaderには開いた使用可能な接続が必要です。接続の現在の状態は閉じています」という正確なエラーを再現するにはどうすればよいですか。

4

3 に答える 3

20

いいえ、たくさんのSqlConnectionオブジェクトを作成し、完了したらそれぞれを閉じることは非効率ではありません。それはまさに正しいことです。.NET フレームワークの接続プールに任せてください。自分でやろうとしないでください。接続プールを有効にするために特別なことをする必要はありません (ただしPooling=false、接続文字列で設定することで無効にすることができます)。

自分で接続をキャッシュしようとすると、うまくいかないことがたくさんあります。いやだっていうだけだよ :)

于 2009-06-29T14:22:59.570 に答える
2

接続文字列で接続プールを有効にする必要があります。その場合、ランタイムは、実際に切断するのではなく、接続を閉じるときに接続を「プール」に戻します。「新しい」接続がプールから取り出されると、それはリセットされ (つまり、sp_reset_connection が呼び出されます)、アプリケーションに新しい新しい接続として提示されます。プールは、プールでのアイドリング中に接続が閉じられた場合など、透過的に処理されます。

認証にはクライアントとサーバーの間で数回のラウンドトリップが必要になるため、「ゼロから」新しい接続を作成するコストは重要です (認証方法と SSL 設定によっては、最良の場合は 1 ラウンドトリップ、悪い場合は約 10 ラウンドトリップになる可能性があります)。

あなたの質問に答えるために、接続は状態が変化したときにOnStateChangeイベントを発生させますが、プーリングを使用する場合はこれを気にする必要はありません。

于 2009-06-29T14:29:30.397 に答える
1

私の最近の経験では、このコードを使用する場合:

using(SQLConnection conn = new SQLConnection(connectionString))
{
    // do stuff with conn
}

エラーがあり、接続を明示的に閉じないでください。接続は閉じられず、プールにチェックインされません。したがって、catch または finally ブロックを使用して接続を閉じます

于 2012-01-07T20:04:32.597 に答える