2012-02-02 76 views
1

我们的生产服务器终止了不活动的连接,所以我们的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); 
    } 

我该如何重构我的代码并消除重复?我需要保留这些方法的签名,因为它们在整个系统中都被使用。

+0

您是否想过将方法提取到接口..?也没有重复所以说一个方法是无效的,而另一个返回一个SQLReader,你可能通过使用一种方法并使用参数只是一个建议,可以消除这一点 – MethodMan 2012-02-02 21:59:35

+0

@DJKRAZE:是的,我做到了。但是,第一个方法返回SqlDataReader,而第二个方法是void。 – 2012-02-02 22:01:40

+0

你可以将重复的逻辑分成另一种方法,你可以从你现有的所有方法中调用并返回一个bool或SqlCommand对象本身(重新连接)然后在其上运行你的操作... NonQuery,ExecuteReader等 – 2012-02-02 22:03:12

回答

5
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()); 
} 
+0

的Bleh ...拍我给它:(这基本上就是我指的是在我的评论。 – 2012-02-02 22:08:53

+0

技术上更改非查询方法的签名。它不应该打破代码除非在特殊情况下,但它仍然值得一提。 – Servy 2012-02-02 22:10:41

+0

唐” T优有在'RestoreConnectionAndExecuteNonQuery'? – 2012-02-02 22:11:02

0

这些方法的通用部分是连接检索过程。你可以创建一个新的静态方法,负责那个被称为检索连接的命令作为参数,并返回它,如果在其他情况下建立连接抛出异常。

1
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); 
     } 
0

在代码示例中,我不喜欢一些东西。但是,为了明确回答你关于消除重复的问题 - 将公共代码抽取到一个需要委托的方法中。

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或
  • 为IDisposable的资源使用报表错误代码的消息,而不是(这将在本地化版本的更新版本的FX变化,并有可能)
  • 抛出特定的例外
+0

在你的答案的版本,该方法应该是RestoreConnectionAndExecute 不RestoreConnectionAndExecute 2012-02-02 22:16:56

+0

+1我切换到Exception.Number。但是,使用语句不能解决我的问题。 – 2012-02-03 21:00:26

相关问题