无法捕获DbUpdateConcurrencyException并抛出UserFriendlyException

时间:2018-11-26 14:46:27

标签: c# entity-framework asp.net-mvc-5 aspnetboilerplate optimistic-concurrency

我正在将ASP.NET Boilerplate与代码优先实体框架和MVC 5一起使用。 我要处理并发。在Update方法中,我在实体中为Timestamp字段添加了RowVersion数据注释。

在我的实体的管理者和Update操作中,我试图捕获DbUpdateConcurrencyException异常并抛出UserFriendlyException,但是由于UpdateAsync是异步的,所以我没有知道在哪里处理异常。

我应该在哪里处理此异常以使其易于使用并且不看到内部服务器错误?

public abstract class BaseFullAuditedEntity : FullAuditedEntity<Guid>
{
    [Timestamp]
    public byte[] RowVersion { get; set; }
}

public class Branch : BaseFullAuditedEntity
{
    public string Name { get; set; }
}

经理代码:

public interface IBranchManager : IDomainService
{
    Task<Branch> Update(Branch branch, byte[] RowVersion);
}

public class BranchManager : DomainService, IBranchManager
{
    private IRepository<Branch, Guid> _branchRepository { get; }

    public async Task<Branch> Update(Branch branch, byte[] RowVersion)
    {
        try
        {
            return await _branchRepository.UpdateAsync(branch);
        }
        catch (DbUpdateConcurrencyException ex)
        {
            throw new UserFriendlyException("Update Concurrency Happened");
        }
    }
}

2 个答案:

答案 0 :(得分:1)

尝试捕获作为总体异常... (有时,真正的异常正在被包装。)

try
{
    // code...
}
catch (Exception ex)
{
    if (ex is AggregateException)
    {
        var exMsg = FlattenAggregate((AggregateException)ex);
        throw new UserFriendlyException(exMsg );
    }

    throw;
}

public static string FlattenAggregate(AggregateException aggregateException)
{
    var sbErr = new StringBuilder();
    var exceptions = aggregateException.Flatten();
    foreach (var exception in exceptions.InnerExceptions)
    {
        sbErr.AppendLine(exception.ToString());
    }

    return sbErr.ToString();
}

答案 1 :(得分:1)

UpdateAsync(branch)仅将branch添加到上下文中。

注入IUnitOfWorkManagerawait SaveChangesAsync()

try
{
    await _branchRepository.UpdateAsync(branch);
    await _unitOfWorkManager.Current.SaveChangesAsync(); // Add this
    return branch;
}
catch (DbUpdateConcurrencyException ex)
{
    throw new UserFriendlyException("Update Concurrency Happened");
}

或者,在您的SaveChanges中覆盖SaveChangesAsyncDbContext以捕获所有实体:

public override int SaveChanges()
{
    try
    {
        return base.SaveChanges();
    }
    catch (DbUpdateConcurrencyException ex)
    {
        throw new UserFriendlyException("Update Concurrency Happened");
    }
}

public override async Task<int> SaveChangesAsync()
{
    try
    {
        return await base.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException ex)
    {
        throw new UserFriendlyException("Update Concurrency Happened");
    }
}