La mise en œuvre de logique de nouvelle tentative de blocage des exceptions
J'ai mis en place un référentiel générique et je me demandais si il n'y est une façon intelligente de mettre en œuvre une logique de nouvelle tentative en cas d'impasse exception?
La démarche doit être la même pour tous référentiel de méthodes. Donc, il y a de toute façon je peux éviter d'écrire 'try/catch - méthode call de nouveau avec retry-comte", dans chaque méthode unique?
Tout suggetsion sont les bienvenus.
Un peu de mon code de Référentiel:
public class GenericRepository : IRepository
{
private ObjectContext _context;
public List<TEntity> ExecuteStoreQuery<TEntity>(string commandText, params object[] parameters) where TEntity : class
{
List<TEntity> myList = new List<TEntity>();
var groupData = _context.ExecuteStoreQuery<TEntity>(commandText, parameters);
return myList;
}
public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
var entityName = GetEntityName<TEntity>();
return _context.CreateQuery<TEntity>(entityName);
}
public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class
{
return GetQuery<TEntity>().AsEnumerable();
}
EDIT:
1.Solution:
Légèrement modifié à partir de chris.maison.00's solution
public static T DeadlockRetryHelper<T>(Func<T> repositoryMethod, int maxRetries)
{
var retryCount = 0;
while (retryCount < maxRetries)
{
try
{
return repositoryMethod();
}
catch (System.Data.SqlClient.SqlException ex)
{
if (ex.Number == 1205)//Deadlock
retryCount++;
else
throw;
}
}
return default(T);
}
Et vous l'appeler comme ceci:
public TEntity FirstOrDefault<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
{
return RetryUtility.DeadlockRetryHelper<TEntity>( () =>p_FirstOrDefault<TEntity>(predicate), 3);
}
protected TEntity p_FirstOrDefault<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
{
return GetQuery<TEntity>().FirstOrDefault<TEntity>(predicate);
}
- Quoi de mal avec une instruction try?
- Je pense que l'OP veut éviter de répéter les blocs try...catch dans chaque pensions de méthode.
- Assurer votre référentiel peut gérer les tentatives de blocage pourrait être difficile. Même si vous consolidez les appels vers le référentiel, chaque respository fonction devra encore être testé.
Vous devez vous connecter pour publier un commentaire.
Comment quelque chose comme cela:
Avec le code ci-dessus, votre logique de nouvelle tentative est tous dans cette méthode et vous pouvez passer votre référentiel de la méthode en tant que délégué.
catch (SqlException ex) when (ex.Number == 1205)
Je sais que c'est un vieux post, mais je voulais partager une mise à jour de réponse.
EF 6 a maintenant une solution intégrée, vous pouvez définir la stratégie d'exécution qui serait un temps de mise en œuvre. Vous créez une classe qui hérite de DbExectutionStrategy et remplace la ShouldRetryOn méthode virtuelle. Vous pouvez créer une classe statique des exceptions contenant champ constant valuess qui sont réessayer admissibles codes et boucle à travers chacun de déterminer si le cours de sql exception levée correspond à la liste des admissibles réessayer codes...
Enfin, une fois, vous avez mis en place votre personnalisé de l'exécution de la stratégie, il vous suffit de créer une autre classe qui hérite de DbConfiguration avec un constructeur public qui Définit la stratégie d'exécution:
EntityFramework 6
ajouterExecutionStrategy
fonctionnalité. Tout ce qui est nécessaire est de configurer correctement la stratégie.Mon réessayer politique:
Dire EF pour appliquer ma stratégie:
Sources:
Les tentatives de stratégie ne fonctionnera pas avec initiées par l'utilisateur des transactions (transaction créé avec
TransactionScope
) comme expliqué ici. Si elle est utilisée, vous obtiendrez l'ErreurThe configured execution strategy does not support user initiated transactions
Avez-vous considéré comme une certaine forme de politique de l'injection? Vous pouvez utiliser l'Unité d'interception, par exemple, pour capturer tous vos référentiel des appels. Ensuite, il vous suffit d'écrire la logique de nouvelle tentative une fois, dans l'intercepteur, plutôt que de répéter plusieurs fois dans chaque méthode.
La solution fonctionne mais je préfère ne pas avoir à vous soucier du nombre d'arguments de la
Action
ouFunc
qui seront à la retraite. Si vous créez une nouvelle tentative de la méthode avec un génériqueAction
, vous pouvez gérer l'ensemble de la variabilité de la méthode à appeler dans un lambda:De l'utiliser ensuite comme suit: