2012-02-02 4 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를 반환하는 반면, 하나의 메서드를 사용하고 params를 사용하여이 문제를 해결할 수 있습니다. – MethodMan

+0

@DJKRAZE : 예, 했었습니다. 그러나 첫 번째 메서드는 SqlDataReader를 반환하고 두 번째 메서드는 void입니다. –

+0

중복 로직을 기존의 모든 메소드에서 호출하여 bool 또는 SqlCommand 객체 자체를 다시 연결 한 다음 다시 조작 할 수있는 다른 메소드로 나눌 수 있습니다 ... NonQuery, ExecuteReader etc. –

답변

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 ... beat 나에게 :(이것은 기본적으로 내가 내 코멘트에서 언급 한 것입니다. –

+0

기술적으로 비 쿼리 메서드의 서명을 변경합니다. 예외적 인 경우를 제외하고는 코드를 중단하면 안되지만 여전히 언급 할 가치가 있습니다. – Servy

+0

Don ' 당신은'RestoreConnectionAndExecuteNonQuery'에서 타입이 일치하지 않습니다? –

0

공통적 인 부분은 연결 검색 프로세스입니다. 예를 들어, 인수로 명령을 취하는 연결을 검색하고 연결이 설정된 경우 예외를 반환하는 호출에 대한 책임이있는 새 정적 메서드를 만들어 다른 예외를 throw 할 수 있습니다.

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

내가 코드 샘플에서 좋아하지 않는 몇 가지 사항이 있습니다. 하지만 명시 적으로 중복 제거에 대한 질문에 대답하려면 - 공용 코드를 추출하여 대리인을 사용하는 메서드로 가져옵니다.

실제로 몇 가지 사항을 다시 생각해보십시오. 포함 : Exception.Number 또는 (업데이트 FX 버전에서 가능 지역화 된 버전에서 변경 한 것) 대신 메시지의 ErrorCode가는 IDisposable 자원에 대한

  • 사용하여 문을 사용

    • 잡기 특정 예외
    • 특정 예외를 던지십시오.
  • +0

    답변 버전에서 메소드는 RestoreConnectionAndExecute 0이어야합니다.아니 RestoreConnectionAndExecute

    +0

    +1 나는 Exception.Number로 전환했습니다. 그러나 문을 사용하여 내 문제가 해결되지 않았습니다. –

    관련 문제