实体框架 - IsUnique的ErrorMessage

时间:2016-12-09 13:43:32

标签: c# asp.net asp.net-mvc entity-framework

是否可以选择执行以下操作:

[Required(ErrorMessage = "This field is required.")]
public string Name { get; set; }

有关:

[Index(IsUnique = true)]
public string Name { get; set; }

问题是,如果他试图通过使用以下方法将Name属性复制到数据库,我想向用户显示验证消息:

@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })

1 个答案:

答案 0 :(得分:1)

为了使用客户端验证来执行此操作,您需要进行AJAX调用以查询数据库并检查名称是否唯一。您仍然需要服务器端验证来捕获系统尝试插入重复名称时发生的唯一约束违规,因为在您检查和尝试插入之间可能会创建重复的名称。

我不会尝试在客户端处理此问题,我只在服务器端执行此操作。假设该操作被称为CreateUser,这里是如何在post操作中的try-catch块中处理它:

try
{
    // create object and save changes
    // EF will be throw a DbUpdateException if the insert fails
    // redirect to action
}
catch (DbUpdateException ex)
{
    if (ExceptionHelper.IsUniqueConstraintViolation(ex))
    {
        ModelState.AddModelError("Name", $"The Name '{viewModel.Name}' is already in use, please enter a different name.");
        return View(nameof(CreateUser), viewModel);
    }
}

异常检测是特定于数据库的,这适用于SQL Server:

public static class ExceptionHelper
{
    private static Exception GetInnermostException(Exception ex)
    {
        while (ex.InnerException != null)
        {
            ex = ex.InnerException;
        }
        return ex;
    }

    public static bool IsUniqueConstraintViolation(Exception ex)
    {
        var innermost = GetInnermostException(ex);
        var sqlException = innermost as SqlException;

        return sqlException != null && sqlException.Class == 14 && (sqlException.Number == 2601 || sqlException.Number == 2627);
    }
}

如果用户持久且继续尝试使用相同的名称,您可以在视图模型中返回先前尝试过的名称,并进行客户端验证以防止重新尝试。