1

最近,我们的 QA 团队在我们的一个应用程序中报告了一个非常有趣的错误。我们的应用程序是一个基于 C# .Net 3.5 SP1 的应用程序,它与 SQL Server 2005 Express Edition 数据库交互。

按照设计,该应用程序被开发用于检测数据库离线场景,如果是这样,则等待数据库在线(通过及时重试连接),一旦在线,重新连接并恢复功能。

我们的 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();

我们注意到另外两件奇怪的事情。1.上述情况发生在代码中的CommandType.Text类型命令。我们的应用程序也使用相同的逻辑来调用存储过程,但我们从来没有遇到过存储过程的这个问题。2. 到目前为止,无论我们在 Visual Studio 的 Debug 模式下尝试了多少不同的方法,我们都无法重现此问题。

提前致谢..

4

3 回答 3

1

I think with almost 3 days of asking the question and close to 20 views of the question and 1 answer, I have to conclude that this is not a scenario that we can handle in the way we have tried with SQL server.

The best way to mitigate this issue in your application is to re-create the SqlCommand object instance again once the application detects that the database is online.

We did the change in our application and our QA team is happy about this modification since it provided the best (or maybe the only) fix for the issue they reported.

A final thanks to everyone who viewed and answered the question.

于 2011-09-05T09:09:19.693 回答
0

当您调用“command.Prepare”时,服务器会缓存查询计划。该错误表明当您再次调用“准备”时它找不到这个缓存的查询计划。尝试创建一个新的“SqlCommand”实例并在其上调用查询。我之前遇到过这个异常,当服务器刷新缓存时它会自行修复。我怀疑是否可以在客户端以编程方式完成任何事情来解决这个问题。

于 2011-09-03T06:01:21.953 回答
0

这不一定与您的问题完全相关,但我发布了这个,因为我花了几天时间试图在我的应用程序中修复相同的错误消息。我们有一个使用 C3P0 连接池、JTDS 驱动程序连接到 SQL Server 数据库的 Java 应用程序。

我们在 C3P0 连接池中禁用了语句缓存,但没有在驱动程序级别执行此操作。将maxStatements=0添加到我们的连接 URL 会停止驱动程序缓存语句,并修复错误。

于 2015-07-23T10:47:20.853 回答