最近、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のデバッグモードでさまざまな方法を試しても、この問題を再現することはできませんでした。
前もって感謝します..