2011-09-03 146 views
1

最近,我们的QA团队在我们的一个应用程序中报告了一个非常有趣的错误。我们的应用程序是一个基于C#.Net 3.5 SP1的应用程序,与SQL Server 2005 Express Edition数据库进行交互。SQL Server:无法找到带有句柄的准备语句x

通过设计中的应用开发,以检测数据库脱机的情况,如果是等到数据库联机(由重试及时进行连接),一旦上线,重新连接和恢复功能。

什么我们的QA团队所做的是,在该应用从数据库中检索的大量数据,停止数据库服务器,等待一段时间,然后重新启动数据库。一旦数据库重新启动,应用程序将重新连接到数据库而没有任何问题,但它开始不断地报告异常“无法找到带有句柄x的预处理语句”(x是某个数字)。

我们的应用程序使用预处理语句,它是专门设计,再次调用prepare()方法对所有的SqlCommand对象时,应用程序重新连接到数据库。例如,

在应用启动时,

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模式下尝试多少种不同的方式,都无法重现此问题。

在此先感谢..

回答

1

我觉得差不多有3天的时间提出这个问题,并且接近20个观点的问题和1个答案,我不得不得出结论,这不是我们可以用我们用SQL服务器尝试的方式处理的情况。

在你的应用程序,以减轻这一问题的最好办法是,一旦应用程序检测到数据库联机再次重新创建SqlCommand对象实例。

我们确实在我们的应用程序的变化,我们的QA团队很高兴这个修改,因为它提供了最好的(也许是唯一)解决他们报告的问题。

最后感谢大家谁查看和回答了这个问题。

0

服务器缓存,当你调用“command.Prepare”的查询计划。该错误表示在您再次调用“Prepare”时无法找到此缓存的查询计划。尝试创建一个新的'SqlCommand'实例并在其上调用查询。我以前遇到过这个异常,当服务器刷新缓存时它会自行修复。我怀疑有什么可以在客户端以编程方式完成,以解决这个问题。

+0

感谢您的回复。我还怀疑是否有任何事情可以解决这个问题,而不是在重新连接数据库时重新创建SqlCommand实例。我们已经尝试过这一点,它当然在起作用。但是,我们在基于Oracle 11g R2数据库的中央数据中心应用程序中尝试了这一点,在数据库关闭并重新启动后,这种仅调用Prepare()的逻辑没有任何问题。这就是为什么我们想知道为什么它不适用于SQL Server。也许'Oracle + ODAC'比'SQL server + SqlClient'更聪明...... :) –

+0

这是一个Sql Server特定的错误。它不会在Oracle数据库上发生。 – alwayslearning

0

这没有必然的关系究竟你的问题,但我张贴这是我花了几天想在我的应用程序来解决同样的错误消息。我们有一个Java应用程序使用C3P0连接池,JTDS驱动程序,连接到SQL Server数据库。

我们在C3P0连接池中禁用了语句缓存,但是在驱动程序级别上没有这样做。向我们的连接URL添加maxStatements = 0停止了驱动程序缓存语句,并修复了错误。