2017-10-02 1 views
0

Existe-t-il un package/DLL ASP.NET qui permet à l'exécution de la requête MySQL de réessayer en cas d'échec?L'exécution de la requête MySQL ASP.NET C# réessaie en cas d'échec

J'ai lu à propos de Transient Fault Handling et j'ai même rencontré un Dapper issue which shows an example mais d'après mes recherches cela ne fonctionne qu'avec SqlServer et/ou Azure.

Ma pile de technologie est la suivante:

  • .NET 4.5.2
  • Dapper 1.50.2.0
  • MySQL 5.6 (avec Amazon Aurora)

En fin de compte, je suis en train de résoudre un sporadic failure issue et je crois que la mise en œuvre de la logique de réessai aiderait à résoudre le problème.

J'ai essayé d'implémenter du code à partir de ce Dapper issue mais comme j'utilise MySql.Data pour me connecter à ma base de données MySql, cela ne fonctionne pas avec les diverses méthodes spécifiques aux connexions SqlServer.

using System; 
using System.Collections.Generic; 
using System.Data; 
using System.Data.SqlClient; 
using Dapper; 
using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling; 

namespace TransientDapper 
{ 
    public static class TransientDapperExtensions 
    { 
     private static readonly RetryManager SqlRetryManager = GetDefaultRetryManager(); 
     private static readonly RetryPolicy SqlCommandRetryPolicy = SqlRetryManager.GetDefaultSqlCommandRetryPolicy(); 
     private static readonly RetryPolicy SqlConnectionRetryPolicy = 
      SqlRetryManager.GetDefaultSqlConnectionRetryPolicy(); 

     private static RetryManager GetDefaultRetryManager() 
     { 
      const int retryCount = 4; 
      const int minBackoffDelayMilliseconds = 2000; 
      const int maxBackoffDelayMilliseconds = 8000; 
      const int deltaBackoffMilliseconds = 2000; 

      var exponentialBackoffStrategy = 
       new ExponentialBackoff(
        "exponentialBackoffStrategy", 
        retryCount, 
        TimeSpan.FromMilliseconds(minBackoffDelayMilliseconds), 
        TimeSpan.FromMilliseconds(maxBackoffDelayMilliseconds), 
        TimeSpan.FromMilliseconds(deltaBackoffMilliseconds) 
        ); 

      var manager = new RetryManager(
       new List<RetryStrategy> 
       { 
        exponentialBackoffStrategy 
       }, 
       exponentialBackoffStrategy.Name 
       ); 

      return manager; 
     } 

     public static void OpenWithRetry(this SqlConnection cnn) 
     { 
      cnn.OpenWithRetry(SqlConnectionRetryPolicy); 
     } 

     public static IEnumerable<T> QueryWithRetry<T>(
      this SqlConnection cnn, string sql, object param = null, IDbTransaction transaction = null, 
      bool buffered = true, int? commandTimeout = null, CommandType? commandType = null 
      ) 
     { 
      return SqlCommandRetryPolicy.ExecuteAction(
       () => cnn.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType) 
       ); 
     } 
    } 
} 

Répondre

0

Peu de temps après la publication, je trouve un paquet appelé Polly qui semble résoudre ce problème « nouvelle tentative ». Je l'ai retrouvé via cette StackOverflow question.

Voici ma mise en œuvre pour effectuer des requêtes à partir d'une base de données MySQL et une nouvelle tentative en cas d'échec:

var policy = Policy 
    .Handle<AuthenticationException>(ex => ex.InnerException is Win32Exception) 
    .Or<AuthenticationException>() 
    .Retry((exception, attempt) => 
    {       
     Log.Error(exception, "Class: {Class} | Method: {Method} | Failure executing query, on attempt number: {Attempt}", GetType().Name, 
      MethodBase.GetCurrentMethod().Name, attempt); 
    }); 

try 
{ 
    var token = new Token(); 

    policy.Execute(() => 
    { 
     using (var connection = _mySqlDatabase.GetConnection()) 
     { 
      token = connection.Query<Token>("SELECT * FROM Token...").FirstOrDefault(); 
     } 
    }); 

    return token; 
} 
catch (Exception ex) 
{ 
    Log.Error(ex, "Class: {Class} | Method: {Method} | Ultimately failed to retrieve data from the database", GetType().Name, 
     MethodBase.GetCurrentMethod().Name); 
    throw new HttpError(HttpStatusCode.InternalServerError); 
}