如何以及在何处使用 Entity Framework Core 6 验证 ASP.NET Core MVC 中 attribute/property 的唯一性

How and where to validate uniqueness of attribute/property in ASP.NET Core MVC using Entity Framework Core 6

我想检查一下,用户 table 记录中没有已存储的特定电子邮件。

如果存在,则 ModelState.IsValid return控制器操作为 false。

我理解唯一约束的需要,我理解竞态条件的问题。我现在不关心这些。

此时我只想在正确的位置查询数据并使模型无效后,将 ModelState.IsValid 设为 return false。

我是否应该实施这样的验证:

  1. DbContext?
  2. 在我的实体 classes(用户/公司等)中?
  3. SomeCustomValidation class?
  4. 直接在控制器中(因为在那里我已经可以查询数据库了...)
  5. 其他地方...

而且不错的好处是创建可在所有实体中重复使用的解决方案:)

我应该怎么做?

更好的方法是在每次插入或更新之前检查它:

if(db.Table.Any(x => x.UniqueCloumn == newValue))
    error = "this record is already exist"
else
{  
    db.Table.Add(newObject);
    db.Savechanges() 
}

还有一些我不推荐的可重用代码方法: https://www.codeproject.com/Tips/1143215/Validate-a-Unique-Constraint-at-dbContext-Validate

您可以像下面这样自定义验证属性:

public class TestEmailAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value,
        ValidationContext validationContext)
    {
        var context = (YourDbContext)validationContext.GetService(typeof(YourDbContext));
        if(!context.User.Any(a=>a.Email==value.ToString()))
        {
            return ValidationResult.Success;
        }
        return new ValidationResult("Email exists");
    }
}

型号:

public class User
{
    public int Id { get; set; }
    [TestEmail]
    public string Email { get; set; }
}

视图(Test.cshtml):

@model User
<form method="post" asp-action="Test" asp-controller="Home">   
    <div class="form-group">
        <input asp-for="Email" />
        <span asp-validation-for="Email" class="text-danger"></span>
    </div>

    <input type="submit" value="Post"/>
</form>

控制器:

//GET render the Test.cshtml
public async Task<IActionResult> Test()
{
    return View();
}
[HttpPost]
public async Task<IActionResult> Test(User user)
{
    if(!ModelState.IsValid)
    {
        return View(user);
    }
    return RedirectToAction("Index");
}