1

最近、QAチームが、アプリケーションの1つに非常に興味深いバグを報告しました。このアプリケーションは、SQL Server 2005 Express Editionデータベースと対話するC#.Net3.5SP1ベースのアプリケーションです。

設計上、アプリケーションはデータベースのオフラインシナリオを検出するように開発されており、データベースがオンラインになるまで待機し(タイムリーに接続を再試行することにより)、オンラインになったら再接続して機能を再開します。

私たちのQAチームが行ったことは、アプリケーションがデータベースから大量のデータを取得している間に、データベースサーバーを停止し、しばらく待ってからデータベースを再起動することでした。データベースが再起動すると、アプリケーションは問題なくデータベースに再接続しますが、「ハンドルxのプリペアドステートメントが見つかりませんでした」(xはいくつかの数値)という例外を継続的に報告し始めました。

このアプリケーションはプリペアドステートメントを使用しており、アプリケーションがデータベースに再接続したときに、すべてのSqlCommandオブジェクトでPrepare()メソッドを再度呼び出すようにすでに設計されています。例えば、

アプリケーションの起動時に、

    SqlCommand _commandA = connection.CreateCommand();
    _commandA.CommandText = @"SELECT COMPANYNAME FROM TBCOMPANY WHERE ID = @ID";
    _commandA.CommandType = CommandType.Text;
    SqlParameter _paramA = _commandA.CreateParameter();
    _paramA.ParameterName = "@ID";
    _paramA.SqlDbType = SqlDbType.Int;
    _paramA.Direction = ParameterDirection.Input;
    _paramA.Size = 0;
    _commandA.Parameters.Add(_paramA);
    _commandA.Prepare();

その後、この_commandAでExceuteReader()を使用し、アプリケーションの各サイクルで異なる@IDパラメーター値を使用します。

アプリケーションがデータベースがオフラインになりオンラインに戻ることを検出すると、データベースに再接続すると、アプリケーションは実行されるだけです。

    _commandA.Prepare();

私たちが気付いたもう2つの奇妙なこと。1.上記の状況は、コード内のCommandType.Textタイプコマンドで発生します。このアプリケーションもまったく同じロジックを使用してストアドプロシージャを呼び出しますが、ストアドプロシージャでこの問題が発生することはありません。2.これまで、Visual Studioのデバッグモードでさまざまな方法を試しても、この問題を再現することはできませんでした。

前もって感謝します..

4

3 に答える 3

1

ほぼ3日間の質問と、20回近くの質問と1つの回答から、これはSQLServerで試した方法で処理できるシナリオではないと結論付ける必要があります。

アプリケーションでこの問題を軽減する最善の方法は、データベースがオンラインであることをアプリケーションが検出したら、SqlCommandオブジェクトインスタンスを再作成することです。

アプリケーションに変更を加えました。QAチームは、報告された問題に対して最良の(またはおそらく唯一の)修正を提供したため、この変更に満足しています。

最後に、質問を見て回答してくれたすべての人に感謝します。

于 2011-09-05T09:09:19.693 に答える
0

'command.Prepare'を呼び出すと、サーバーはクエリプランをキャッシュします。このエラーは、「準備」を再度呼び出すと、このキャッシュされたクエリプランが見つからないことを示しています。新しい「SqlCommand」インスタンスを作成し、そのインスタンスでクエリを呼び出してみてください。私は以前にこの例外を経験しましたが、サーバーがキャッシュを更新すると自動的に修正されます。これを修正するために、クライアント側でプログラム的に実行できるものがあるとは思えません。

于 2011-09-03T06:01:21.953 に答える
0

これは必ずしもあなたの問題に正確に関連しているわけではありませんが、アプリケーションで同じエラーメッセージを修正するために数日を費やしたので、これを投稿します。C3P0接続プールであるJTDSドライバーを使用してSQLServerデータベースに接続するJavaアプリケーションがあります。

C3P0接続プールでステートメントキャッシュを無効にしましたが、ドライバーレベルでは無効にしませんでした。接続URLにmaxStatements=0を追加すると、ドライバーのキャッシュステートメントが停止し、エラーが修正されました。

于 2015-07-23T10:47:20.853 に答える