Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing retry logic for deadlock exceptions

I've implemented a generic repository and was wondering if there is a smart way to implement a retry logic in case of a deadlock exception?

The approach should be the same for all repository methods. So is there anyway I can avoid writing 'try/catch - call method again with retry-count', in every single method?

Any suggetsion are welcome.

A bit of my Repository code:

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:

Modified slightly from chris.house.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);     } 

And you call it like this:

    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);     } 
like image 824
user1638662 Avatar asked Oct 31 '12 13:10

user1638662


1 Answers

How about something like this:

public T DeadlockRetryHelper<T>(Func<T> repositoryMethod, int maxRetries) {   int retryCount = 0;    while (retryCount < maxRetries)   {     try     {       return repositoryMethod();     }     catch (SqlException e) // This example is for SQL Server, change the exception type/logic if you're using another DBMS     {       if (e.Number == 1205)  // SQL Server error code for deadlock       {         retryCount++;       }       else       {         throw;  // Not a deadlock so throw the exception       }       // Add some code to do whatever you want with the exception once you've exceeded the max. retries     }   } } 

With the above code, your retry logic is all in this method and you can just pass your repository method in as a delegate.

like image 73
chris.house.00 Avatar answered Sep 22 '22 06:09

chris.house.00