无法捕获 DbUpdateConcurrencyException 并抛出 UserFriendlyException

Unable to catch DbUpdateConcurrencyException and throw UserFriendlyException

我正在使用 ASP.NET 带有代码优先 Entity Framework 和 MVC 5 的样板。 我想处理并发。在 Update 方法中,我在我的实体中为 RowVersion 字段放置了 Timestamp 数据注释。

在我的实体管理器和 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");
        }
    }
}

尝试作为聚合异常进行捕获... (有时,真正的异常正在被包装。)

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

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

或者,覆盖 DbContext 中的 SaveChangesSaveChangesAsync 以捕获所有实体:

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