实施重试死锁例外逻辑 [英] Implementing retry logic for deadlock exceptions

查看:238
本文介绍了实施重试死锁例外逻辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了一个通用的存储库,并想知道是否有实现死锁异常的情况下,重试逻辑的聪明的方式?



的方法应该是同样为所有存储库的方法。那么,有没有反正我可以回避写'的try / catch - 与重试计数再次调用方法'?,在每一个方法



任何suggetsion欢迎



我的库代码了一下:

 公共类GenericRepository:IRepository 
{
私人ObjectContext的_context;

公开名单< TEntity> ExecuteStoreQuery< TEntity>(字符串的CommandText,params对象[]参数)其中TEntity:类
{
名单,LT; TEntity> myList中=新名单< TEntity>();

VAR groupData = _context.ExecuteStoreQuery< TEntity>(CommandText中,参数);

返回myList中;
}


公众的IQueryable< TEntity> GetQuery< TEntity>()其中TEntity:类
{
变种的entityName = GetEntityName< TEntity>();
返回_context.CreateQuery< TEntity>(的entityName);
}

公开的IEnumerable< TEntity> GETALL< TEntity>()其中TEntity:类
{
返回GetQuery< TEntity>()AsEnumerable();
}



编辑:



1.Solution:



从稍微修改 chris.house.00 小号的

 公共静态牛逼DeadlockRetryHelper< T>(Func键< T> repositoryMethod,诠释maxRetries) 
{
变种RetryCount重= 0;

,而(RetryCount重< maxRetries)
{

{
返回repositoryMethod();
}
赶上(System.Data.SqlClient.SqlException前)
{
如果(ex.Number == 1205)//死锁
RetryCount重++;
,否则
扔;
}
}
返回默认值(T);
}

和你这样称呼它:

 公共TEntity FirstOrDefault< TEntity>(表达式来; Func键< TEntity,布尔>>谓语)其中TEntity:类
{
返回RetryUtility。 DeadlockRetryHelper&所述; TEntity>(()=> p_FirstOrDefault&下; TEntity>(谓词),3);
}

保护TEntity p_FirstOrDefault< TEntity>(表达式来; Func键< TEntity,布尔>>谓语)其中TEntity:类
{
返回GetQuery< TEntity> ().FirstOrDefault< TEntity>(谓语);
}


解决方案

如何是这样的:

 公共牛逼DeadlockRetryHelper< T>(Func键< T> repositoryMethod,诠释maxRetries)
{
INT RetryCount重= 0;

,而(RetryCount重< maxRetries)
{

{
返回repositoryMethod();
}
赶上(SQLEXCEPTION E)//这个例子是SQL Server,如果您正在使用另一个DBMS
{
如果改变异常类型/逻辑(e.Number == 1205)//死锁
{
RetryCount重++ SQL Server错误代码;
}
,否则
{
扔; //不是死锁所以抛出异常
}
//添加一些代码,做你想做的不同之处,一旦你超过了最大值重试
}
}
}

通过上面的代码,您重试逻辑是所有这个方法,你可以通过你的仓库方法作为代表。


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);
    }

解决方案

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.

这篇关于实施重试死锁例外逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆