如何重构冗余的try catch代码

本文关键字:try catch 代码 冗余 何重构 重构 | 更新日期: 2023-09-27 18:14:14

我正在尝试确定重构这段代码的最佳方法。如你所见,尝试…抓住. .抓住. .赶上……代码行是相同的。这两个方法之间的唯一区别是一个是异步的,而另一个不是。

public override int SaveChanges()
{
    try
    {
        return base.SaveChanges();
    }
    catch (DbEntityValidationException ex)
    {
        var entityValidationErrors = ex.EntityValidationErrors
            .SelectMany(e => e.ValidationErrors)
            .Select(x => string.Format("{0} - {1}", x.PropertyName, x.ErrorMessage));
        var fullErrorMessage = string.Join(Environment.NewLine, entityValidationErrors);
        var exceptionMessage = string.Concat(ex.Message, " Entity validation errors: ", fullErrorMessage);
        throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
    }
    catch (DbUpdateConcurrencyException ex)
    {
        Debug.WriteLine(ex.Message);
        throw;
    }
    catch (DbUpdateException ex)
    {                
        var sqlException = ex.GetBaseException() as SqlException;
        if (sqlException == null || sqlException.Errors.Count <= 0) 
            throw;
        var errors = new List<string>();
        for (var i = 0; i < sqlException.Errors.Count; i++)
        {
            errors.Add(string.Format("{0} - {1}", sqlException.Errors[i].Number, sqlException.Errors[i].Message));
        }
        throw new DbUpdateException(string.Join(Environment.NewLine, errors));
    }
}
public override async Task<int> SaveChangesAsync()
{
    try
    {
        return await base.SaveChangesAsync();
    }
    catch (DbEntityValidationException ex)
    {
        var entityValidationErrors = ex.EntityValidationErrors
            .SelectMany(e => e.ValidationErrors)
            .Select(x => string.Format("{0} - {1}", x.PropertyName, x.ErrorMessage));
        var fullErrorMessage = string.Join(Environment.NewLine, entityValidationErrors);
        var exceptionMessage = string.Concat(ex.Message, " Entity validation errors: ", fullErrorMessage);
        throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
    }
    catch (DbUpdateConcurrencyException ex)
    {
        Debug.WriteLine(ex.Message);
        throw;
    }
    catch (DbUpdateException ex)
    {
        var sqlException = ex.GetBaseException() as SqlException;
        if (sqlException == null || sqlException.Errors.Count <= 0)
            throw;
        var errors = new List<string>();
        for (var i = 0; i < sqlException.Errors.Count; i++)
        {
            errors.Add(string.Format("{0} - {1}", sqlException.Errors[i].Number, sqlException.Errors[i].Message));
        }
        throw new DbUpdateException(string.Join(Environment.NewLine, errors));
    }
}

如何重构冗余的try catch代码

同时使用Sync和Async方法的一种方法是在Sync方法和Async方法中使用实际的逻辑来将前者封装到Task中。

public override Task<int> SaveChangesAsync()
{
    return new Task(SaveChanges);
}

我最终使用委托(Func)解决了这个问题。下面是两个"duplicate". savechanges方法。

public override int SaveChanges()
{
    return SaveChangesWrapper<int>(() => base.SaveChanges());
}
public override async Task<int> SaveChangesAsync()
{
    return await SaveChangesWrapper<Task<int>>(async () => await base.SaveChangesAsync());
}

这是包装。

private T SaveChangesWrapper<T>(Func<T> function)
{
    try
    {
        //do some work up front....
        return function();
    }
    catch (DbEntityValidationException ex)
    {
        //parse exception and rethrow...
    }
    catch (DbUpdateConcurrencyException ex)
    {
        //parse and rethrow...
    }
    catch (DbUpdateException ex)
    {
        //parse and rethrow...
    }
    catch (Exception ex)
    {
        //parse and rethrow..
    }
}