c# - 实现死锁异常的重试逻辑

标签 c# entity-framework try-catch repository-pattern database-deadlocks

我已经实现了一个通用存储库,想知道是否有一种智能方法可以在发生死锁异常时实现重试逻辑?

所有存储库方法的方法应该相同。那么我是否可以避免在每个方法中都编写“try/catch - 使用重试计数再次调用方法”?

欢迎提出任何建议。

我的一些存储库代码:

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

编辑:

1.解决方法:

根据chris.house.00解决方案

略作修改
 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);
    }

你这样调用它:

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

最佳答案

这样的事情怎么样:

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

使用上面的代码,您的重试逻辑都在这个方法中,您只需将存储库方法作为委托(delegate)传递即可。

关于c# - 实现死锁异常的重试逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13159326/

相关文章:

c# - 只有标题数据的 WPF Datagrid 水平滚动

c# - 如何动态构建表达式树以用于匿名类型

entity-framework - Azure:在暂存环境中使用 Code First 迁移进行测试的最佳实践

java - java中调用自身的验证方法

java - HttpURLConnection catch block 重复

C#、OLEDB从指定行读取Excel文件

c# - 使用 async/await 时处理节流/速率限制(429 错误)

c# - Entity Framework 6 Oracle 和乐观并发

c# - 尝试阻止被调用两次

C# 如何制作 GetEnumerator() 的递归版本