我们有一个帮助器类,用于在SQL Server上调用存储过程。辅助函数如下所示:
using (sqlCon = new SqlConnection(connectionString))
{
// Create database command object
sqlCmd = sqlCon.CreateCommand();
sqlCmd.CommandTimeout = commandTimeout;
// Set command text AND command type
sqlCmd.CommandText = procedureName;
sqlCmd.CommandType = CommandType.StoredProcedure;
// Set command parameters
if (paramCollection != null)
{
foreach (DatabaseParameter dbParam in paramCollection)
{
SqlParameter sqlParam = sqlCmd.Parameters.Add(dbParam.ParameterName, dbParam.ParameterType);
sqlParam.Direction = dbParam.ParameterDirection;
sqlParam.Value = dbParam.ParameterValue;
if (dbParam.ParameterSize != -1)
sqlParam.Size = dbParam.ParameterSize;
if (dbParam.ParamPrecision != -1)
sqlParam.Precision = (byte)dbParam.ParamPrecision;
if (dbParam.ParamScale != -1)
sqlParam.Scale = (byte)dbParam.ParamScale;
}
}
try
{
sqlCon.Open();
}
catch
{
SqlConnection.ClearAllPools();
sqlCon.Open();
}
// Prepare command
sqlCmd.Prepare();
// Execute the statement
sqlCmd.ExecuteNonQuery();
if (sqlCmd.Parameters.Contains("@Result"))
return sqlCmd.Parameters["@Result"].Value;
else
return "Completed";
}
因此我们确保正确关闭连接。 该应用程序是一个多线程服务,所有线程都经常调用此方法。我们围绕调用上述帮助方法的代码锁定(thisobject){}部分,以防止线程窃取彼此的连接。
connection.Open位于带有ClearAllpools的try catch中,用于清除断开的连接。
但是,我们间歇性地在一天中随机获取以下错误列表。
连接的当前状态正在连接。
或
连接的当前状态已打开。
错误发生在代码调用的每几千次中,因此很难排除故障。有没有人在可能出错的地方看到任何类似或想法?
答案 0 :(得分:1)
嗯,我不能确定连接失败的原因。但是错误的是你的catch
块。你忽略了实际的错误并用一个无用的错误(你正在看到的那个)替换它。
从不忽略异常。它们被抛出是有原因的,并且往往包含有关系统遇到的意外错误的有用信息。你在找出问题时遇到了麻烦,因为你在没有看到它的情况下扔掉了那些有用的信息。
您看到的错误来自catch
块中的代码。这段代码本质上是试图做出失败的确切事情,但方式略有不同。您需要记录错误,以便找出失败的原因并首先到达catch
块。
try/catch
块的一个好的经验法则是,如果你准备处理异常,你应该只捕获异常。在这里你根本不处理它,所以除非你这样做,否则你应该完全删除try/catch
。让异常泡到某个可以处理的地方。或者,将catch
块中的代码替换为一些错误记录,并以有用且有意义的方式退出代码块(将错误返回到调用代码块,抛出自定义异常,其中包含捕获的异常,等)。
答案 1 :(得分:1)
我在处理多线程应用时遇到过这些类型的错误,即使使用lock
也是如此。经过无数个小时的调试后,我从未发现问题,最终在放弃之前尝试重新连接几次。到目前为止,我还没有看到错误再次出现。
int retries = 5;
while( true )
{
try
{
DbCommand cmd = GetCommand( sql );
using( DbConnection conn = cmd.Connection )
{
conn.Open();
// do stuff
break;
}
}
catch
{
Thread.Sleep( 1000 );
if( retries-- <= 0 )
{
throw;
}
}
}
答案 2 :(得分:0)
除此之外,您是否尝试过根据连接的State
有条件地进行处理?
using (sqlCon = new SqlConnection(connectionString))
{
if (sqlCon.State == ConnectionState.Open)
{
....
}
}