2016-04-20 9 views
3

がタイムアウトし、エラーが発生します。クエリを実行するために再試行する最善の方法は何ですか?タイムアウトに失敗した場合はC#再試行クエリクエリがタイムアウトしたときに

クエリを実行する前に接続が開いていることを確認します。ただし、任意の時点でのサーバーの負荷のため、1分から5分以上かかることがあります(<)。私はCommandTimeoutを拡張することを考えましたが、それは実際には行く方法だとは思わない。

ここに私のSQLクエリコードです。すべての支援に感謝します。

private static void ExecuteQuery(string connectionString, string query) 
    { 
     SqlConnection connection = new SqlConnection(connectionString); 
     DataTable output = new DataTable(); 

     try 
     { 
      //create new SqlAdataAdapter 
      SqlDataAdapter command = new SqlDataAdapter {SelectCommand = new SqlCommand(query, connection)}; 

      //connect to Sqldb 
      connection.Open(); 

      //validate connection to database before executing query 
      if (connection.State != ConnectionState.Open) return; 
      Console.WriteLine("Connection successful\nExecuting query..."); 

      //set connection timeout 
      command.SelectCommand.CommandTimeout = 200; 

      //create new dataSet in order to input output of query to 
      DataSet dataSet = new DataSet(); 

      //fill the dataSet 
      command.Fill(dataSet, "capacity"); 
      DataTable dtTable1 = dataSet.Tables["capacity"]; 

      Console.WriteLine("There are " + dtTable1.Rows.Count + " clusters within the capacity anlaysis."); 

      output = dtTable1; 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Unable to execute capacity (all records) query due to {0}", e.Message); 
     } 
     finally 
     { 
      connection.Close(); 

      Declarations.NumOfClusters = output.Rows.Count; 
      Declarations.finalIssues = Issues(output, 2m, 20, true); 

      Console.WriteLine("\n---------------Successfully Created Capacity DataSet---------------\n"); 
     } 
    } 

答えて

1

あなたが望む結果が得られるまで、再帰的にクエリを呼び出すことができるように、構造を再構成します。

例:

private static void ExecuteQuery(string connectionString, string query) 
{ 
    SqlConnection connection = new SqlConnection(connectionString); 
    DataTable output = null; 

    while output is null 
    { 
     output = getDataFromDB(query); 
    } 

    if(output is DataTable && output.Rows.Count > 0) 
    { 
     Console.WriteLine("There are " + output.Rows.Count + " clusters within the capacity analysis."); 
    } 
} 

private DataTable getDataFromDB(string query) 
{ 
    DataTable oDTResult = null; 

    try 
    { 
     //create new SqlAdataAdapter 
     SqlDataAdapter command = new SqlDataAdapter {SelectCommand = new SqlCommand(query, connection)}; 

     //connect to Sqldb 
     connection.Open(); 

     //validate connection to database before executing query 
     if (connection.State != ConnectionState.Open) return; 
     Console.WriteLine("Connection successful\nExecuting query..."); 

     //set connection timeout 
     command.SelectCommand.CommandTimeout = 200; 

     //create new dataSet in order to input output of query to 
     DataSet dataSet = new DataSet(); 

     //fill the dataSet 
     command.Fill(dataSet, "capacity"); 
     DataTable dtTable1 = dataSet.Tables["capacity"];    

     oDTResult = dtTable1; 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine("Unable to execute capacity (all records) query due to {0}", e.Message); 
    } 
    finally 
    { 
     connection.Close(); 

     Declarations.NumOfClusters = output.Rows.Count; 
     Declarations.finalIssues = Issues(output, 2m, 20, true); 

     Console.WriteLine("\n---------------Successfully Created Capacity DataSet---------------\n"); 
    } 

    return oDTResult; 
} 

プログラムで柔軟性を持たせるために、このプログラムを実行しようとするリトライ回数を連想させることができます。さらに

あなたのクエリは、このような長い時間がかかっている場合は、ビュー/インデックスの助けを借りて、あなたが実行時間を削減するために、SQL Serverデータベースを最適化する方法の方法を検討すべきであるなど

0

再試行するための一般的な方法は、あなたが今、再試行ロジックを実行するには、このユーティリティメソッドを使用することができます

public static class Retry 
    { 
     public static void Do(
      Action action, 
      TimeSpan retryInterval, 
      int retryCount = 3) 
     { 
      Do<object>(() => 
      { 
       action(); 
       return null; 
      }, retryInterval, retryCount); 
     } 

     public static T Do<T>(
      Func<T> action, 
      TimeSpan retryInterval, 
      int retryCount = 3) 
     { 
      var exceptions = new List<Exception>(); 

      for (int retry = 0; retry < retryCount; retry++) 
      { 
       try 
       { 
        if (retry > 0) 
         Thread.Sleep(retryInterval); 
        return action(); 
       } 
       catch (Exception ex) 
       { 
        exceptions.Add(ex); 
       } 
      } 

      throw new AggregateException(exceptions); 
      } 
     } 

アクションは:

Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1)); 
0

私はasp.netのWebのサンプルコードを書きますフォームは10回実行されます。

 static int noOfTries = 0; 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      function(); 
     } 

     private void function() 
     { 

      try 
      { 

       if (noOfTries == 10) goto XX; 
       noOfTries++; 
       int a = 0; 
       int b = 1/a; 


      } 
      catch (Exception ew) 
      { 
       Response.Write(ew.Message + "<br/>"); 
       function(); 

      } 
      XX: 
      int c = 0; 
     } 

注: そのは静的変数

static int noOfTries=0 マルチスレッドの実行は、静的変数は、マルチスレッドで共有されるので除いて、あなたのように動作しない場合がありますの使用など、スレッドセーフではありません。

マルチスレッド実行環境場合 Session["noOfTries"]

使用を解決します。

2

使用パーマーライブラリ: https://github.com/mitchdenny/palmer

Retry.On<Exception>().For(TimeSpan.FromSeconds(15)).With(context => 
    { 
    // Code that might periodically fail due to some issues. 
     ExecuteQuery(string connectionString, string query) 
     if (contect.DidExceptionLastTime) 
      Thread.Sleep(200); // what ever you wish 
    }); 

githubページのAPIを参照してください。たとえば、例外のコンテキストをチェックして、例外が発生した場合はしばらくスリープすることができます。 より具体的な例外で再試行できます。 永遠に試してみてください。

関連する問題