显示常见EF Delete语句与引用约束冲突的友好错误

本文关键字:冲突 错误 约束 引用 EF 常见 Delete 语句 显示 | 更新日期: 2023-09-27 18:24:55

我有一个由实体框架支持的WebApi 2服务。当用户试图删除一个与其他实体相关的实体时,我只想向他们显示一条消息,说明他们无法删除该特定项目,因为其他项目与之有关系,然后跳过删除。

我认为这是一个相当常见的场景。我目前正在使用try-catch语句在HTTP响应消息中抛出友好消息。这对我来说就像是一个黑客……我很想听听其他关于处理这件事的建议。

public async Task<IHttpActionResult> DeleteAsync(int id)
    {
        try
        {
            var entity = await TheContext.Fluids.FindAsync(id);
            if (entity == null) return NotFound();
            TheContext.Fluids.Remove(entity);
            await TheContext.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            if (CannotDeleteDueToExistingRelationship(ex))
                ThrowForbiddenCannotDeleteDueToExistingRelationship();
        }
        return Ok();
    }
//Methods in base controller
protected void ThrowForbiddenCannotDeleteDueToExistingRelationship()
    {
        throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden)
        {
            Content = new StringContent(string.Format("This entity has a relationship to another item and cannot be deleted.")),
            ReasonPhrase = "Relationship requires entity."
        });
    }
   protected bool CannotDeleteDueToExistingRelationship(Exception ex)
    {
        if (ex.InnerException.InnerException.Message.Contains("The DELETE statement conflicted with the REFERENCE constraint"))
        {
            return true;
        }
        return false;
    }

显示常见EF Delete语句与引用约束冲突的友好错误

找到它后,答案非常简单。WebAPI 2允许您使用属性过滤器。

 public class DeleteConflictsWithReferenceConstraintExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        if (context.Exception is DbUpdateException)
        {
            if (!(context.Exception as DbUpdateException).InnerException.InnerException.Message.Contains("The DELETE statement conflicted with the REFERENCE constraint")) return;
            var response = new HttpResponseMessage(HttpStatusCode.Forbidden)
            {
                Content = new StringContent(string.Format("This entity has a relationship to another item and cannot be deleted.")),
                ReasonPhrase = "Relationship requires entity."
            };
            context.Response = response;
        }
    }
}

然后在WebApiConfig中注册。

private static void WebApiConfig(IAppBuilder app)
{
    var webApiConfig = new HttpConfiguration();
    webApiConfig.SuppressDefaultHostAuthentication();
    // Web API filters
    webApiConfig.Filters.Add(new DbEntityValidationExceptionAttribute());
    webApiConfig.Filters.Add(new DeleteConflictsWithReferenceConstraintExceptionAttribute());
}

这避免了在任何地方都有相同的异常逻辑。