如何捕获违反数据库约束并抛出 UserFriendlyException?

How to catch DB constraint violation and throw UserFriendlyException?

我有一个 CrudAppService 是这样定义的:

public class MyAppService : AsyncCrudAppService<MyEntity, MyDto, int, PagedAndSortedResultRequestDto, MyCreateDto, MyDto>, IMyAppService, ITransientDependency
{
    private readonly IRepository<MyEntity> _MyRepository;

    public MyAppService(IRepository<MyEntity> repository) : base(repository)
    {
        _MyRepository = repository;
    }
}

我还在实体的字段上定义了一个唯一约束 MyEntity 所以当我尝试创建多个具有相同字段值的实体时,它会中断并抛出一个 DbUpdateException .不错

现在我想捕获此异常并重新抛出 UserFriendlyException 以向用户显示消息。我尝试在 Create() 方法的重写中捕获它,但它没有被捕获。

public override Task<MyDto> Create(MyCreateDto input)
{
    try
    {
        return base.Create(input);
    }
    catch(Exception ex)
    {
        // Never gets here
        throw new UserFriendlyException("A message for the user");
    }
}

所以,我尝试实现 IEventHandler<AbpHandledExceptionData> 来过滤 DbUpdateException 并抛出 UserFriendlyException:

class MyExceptionHandler : IEventHandler<AbpHandledExceptionData>, ITransientDependency
{
    public MyExceptionHandler()
    {
    }

    public void HandleEvent(AbpHandledExceptionData eventData)
    {
        if (eventData.Exception is DbUpdateException dbUpdateEx) {
            throw new UserFriendlyException("A message for the user");
        }
    }
}

调试,我可以看到它到达了throw new UserFriendlyException行,但是没有任何反应(没有消息显示给用户),所以throw new UserFriendlyException行似乎是hidden/ignored.

我该怎么做才能解决这个问题?

谢谢。

您在使用 ASP.NET Core 吗?

因为在 ABP 文档中:(https://aspnetboilerplate.com/Pages/Documents/Handling-Exceptions) 本文档适用于 ASP.NET MVC 和 Web API。如果您对 ASP.NET 核心感兴趣,请参阅 ASP.NET 核心文档。

我必须使用 TempData 和 ViewBag 以模式向用户显示错误...

I tried catching it in an override of the Create() method but it does not get catched.

您需要致电_unitOfWorkManager.Current.SaveChanges():

public override Task<MyDto> Create(MyCreateDto input)
{
    try
    {
        var dto = base.Create(input);
        _unitOfWorkManager.Current.SaveChanges();
        return dto;
    }
    catch (DbUpdateException ex)
    {
        throw new UserFriendlyException("A message for the user");
    }
}

或者,在您的 DbContext 中覆盖 SaveChangesSaveChangesAsync

public override int SaveChanges()
{
    try
    {
        return base.SaveChanges();
    }
    catch (DbUpdateException ex)
    {
        throw new UserFriendlyException("A message for the user");
    }
}

public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
    try
    {
        return await base.SaveChanges();
    }
    catch (DbUpdateException ex)
    {
        throw new UserFriendlyException("A message for the user");
    }
}