如何重用重新打开连接的代码
本文关键字:代码 连接 新打开 何重用 | 更新日期: 2023-09-27 18:22:23
我们的生产服务器会杀死非活动连接,因此我们的API需要在需要时恢复它们。以下代码有效,但非常重复:
private const int MaxRetryCount = 3;
public static SqlDataReader RestoreConnectionAndExecuteReader(SqlCommand command)
{
int retryCount = 0;
while (retryCount++ < MaxRetryCount)
{
try
{
if (command.Connection.State == ConnectionState.Closed)
command.Connection.Open();
return command.ExecuteReader();
}
catch(Exception e)
{
if(!e.Message.ToLower().Contains("transport-level error has occurred"))
{
throw;
}
}
}
throw new Exception("Failed to restore connection for command:"+command.CommandText);
}
public static void RestoreConnectionAndExecuteNonQuery(SqlCommand command)
{
var retryCount = 0;
while(retryCount++ < MaxRetryCount)
{
try
{
if (command.Connection.State == ConnectionState.Closed)
command.Connection.Open();
command.ExecuteNonQuery();
return;
}
catch(Exception e)
{
if (!e.Message.ToLower().Contains("transport-level error has occurred"))
{
throw;
}
}
}
throw new Exception("Failed to restore connection for command:" + command.CommandText);
}
如何重构代码并消除重复?我需要保留这些方法的签名,因为它们在整个系统中都在使用。
private const int MaxRetryCount = 3;
public static T RestoreConnectionAndExecute<T>(SqlCommand command, Func<SqlCommand, T> func)
{
int retryCount = 0;
while (retryCount++ < MaxRetryCount)
{
try
{
if (command.Connection.State == ConnectionState.Closed)
command.Connection.Open();
return func(command);
}
catch(Exception e)
{
if(!e.Message.ToLower().Contains("transport-level error has occurred"))
{
throw;
}
}
}
throw new Exception("Failed to restore connection for command:"+command.CommandText);
}
public static SqlDataReader RestoreConnectionAndExecuteReader(SqlCommand command)
{
return RestoreConnectionAndExecute(command, c => c.ExecuteReader());
}
public static int RestoreConnectionAndExecuteNonQuery(SqlCommand command)
{
return RestoreConnectionAndExecute(command, c => c.ExecuteNonQuery());
}
private const int MaxRetryCount = 3;
public static SqlDataReader RestoreConnectionAndExecuteReader(SqlCommand command)
{
return RestoreConnectionAndExecuteQueryHelper(command, true);
}
public static void RestoreConnectionAndExecuteNonQuery(SqlCommand command)
{
RestoreConnectionAndExecuteQueryHelper(command, false);
}
private static SqlDataReader RestoreConnectionAndExecuteQueryHelper(SqlCommand command, bool returnReader)
{
var retryCount = 0;
while (retryCount++ < MaxRetryCount)
{
try
{
if (command.Connection.State == ConnectionState.Closed)
command.Connection.Open();
if (returnReader)
{
return command.ExecuteReader();
}
else
{
command.ExecuteNonQuery();
return null;
}
}
catch (Exception e)
{
if (!e.Message.ToLower().Contains("transport-level error has occurred"))
{
throw;
}
}
}
throw new Exception("Failed to restore connection for command:" + command.CommandText);
}
这些方法的常见部分是连接检索过程。您可以创建一个新的静态方法来负责调用的连接,例如,检索以命令为参数的连接,并在其他情况下建立连接时返回该连接。
代码示例中有一些东西我不喜欢。但是,要明确地回答您关于消除重复的问题,请将公共代码提取到接受委托的方法中。
private TReturn RestoreConnectionAndExecute<T>(SqlCommand command, Func<SqlCommand, TReturn> execute)
{
int retryCount = 0;
while (retryCount++ < MaxRetryCount)
{
try
{
if (command.Connection.State == ConnectionState.Close)
command.Connection.Open();
return execute(command);
}
catch(Exception e)
{
...
}
}
public SqlDataReader RestoreConnectionAndExecuteReader(SqlCommand command)
{
return this.RestoreConnectionAndExecute(command, c => c.ExecuteReader());
}
public void RestoreConnectionAndExecuteNonQuery(SqlCommand command)
{
// Ignore return
this.RestoreConnectionAndExecute(command, c => c.ExecuteNonQuery());
}
不过,你真的应该重新思考一些事情。其中:
- 捕获特定异常
- 使用Exception.Number或ErrorCode代替消息(这将在本地化版本中发生变化,可能在更新的FX版本中也会发生变化)
- 对IDisposable资源使用语句
- 引发特定异常