最近,我们的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的调试模式下尝试多少种不同的方式,我们都无法重现此问题。
提前致谢..
答案 0 :(得分:1)
我认为通过近3天的提问和近20个问题的观点和1个答案,我必须得出结论,这不是我们用SQL服务器尝试的方式处理的方案。 / p>
在应用程序中缓解此问题的最佳方法是在应用程序检测到数据库联机后再次重新创建SqlCommand对象实例。
我们对我们的应用程序进行了更改,我们的QA团队对此修改感到满意,因为它为他们报告的问题提供了最佳(或可能是唯一的)修复。
最后感谢所有观看和回答问题的人。
答案 1 :(得分:0)
当您调用'command.Prepare'时,服务器会缓存查询计划。该错误表示当您再次调用“准备”时,它无法找到此缓存的查询计划。尝试创建一个新的'SqlCommand'实例并在其上调用查询。我之前遇到过这个异常,它在服务器刷新缓存时自行修复。我怀疑在客户端有什么可以通过编程方式完成,以解决这个问题。
答案 2 :(得分:0)
这并不一定与您的问题完全相关,但我发布了这个,因为我花了几天时间尝试在我的应用程序中修复相同的错误消息。我们有一个使用C3P0连接池,JTDS驱动程序连接到SQL Server数据库的Java应用程序。
我们在C3P0连接池中禁用了语句缓存,但是在驱动程序级别上没有这样做。将 maxStatements = 0 添加到我们的连接URL会停止驱动程序缓存语句,并修复错误。