1

我有一个奇怪的问题。我有一个包含现有项目的数据库,我添加了一个新的验证规则,因此数据库中的某些项目不符合这个新规则。

我有一个循环,可以找到一条记录,更改一个元素,然后将其保存回数据库,如下所示:

foreach(int foo in bar)
{
    Model model = db.Model.Find(foo);
    model.updated = true;
    if(ModelState.IsValid)
    {
        db.Entry(model).State = EntityState.Modified;
        db.SaveChanges();
    }
}

我认为对于不符合新验证规则的记录不会更新,因为ModelState.IsValid不会通过。但情况并非如此,它会引发验证失败异常。所以我把它放进去,try catch然后我想我会记录错误,这样我就知道哪些记录是无效的。所以它现在看起来像这样:

foreach(int foo in bar)
{
    Model model = db.Model.Find(foo);
    model.updated = true;
    try
    {
        db.Entry(model).State = EntityState.Modified;
        db.SaveChanges();
    }
    catch(Exception x)
    {
        // log error
        if(ModelState.IsValid)
        {
            db.ErrorLogs.Add(errorLog);
            db.SaveChanges();
        }
    }
}

这也会引发验证失败异常,我猜是因为try未清除中的异常。很好,我决定尝试一下,而不是发现错误。所以它看起来像这样:

foreach(int foo in bar)
{
    Model model = db.Model.Find(foo);
    model.updated = true;
    try
    {
        db.Entry(model).State = EntityState.Modified;
        db.SaveChanges();
    }
    catch()
    {
    }
}

现在最终发生的事情是说我有 100 条记录通过 foreach 循环循环,如果 #27 验证失败后的每条记录都失败了,因此不会更新!

这非常严重,我该如何解决?有没有办法清除验证错误?为什么错误持续到所有其他循环?是因为db在循环之外声明了吗?为什么它首先通过 ModelState.IsValid ?

谢谢

4

1 回答 1

3

我认为您将 ASP.NET MVC 验证与实体框架的验证混淆了。

  • ModelState.IsValid检查绑定到 MVC Action 参数的模型的有效性。
  • 实体框架对它尝试保存的实体进行自己的验证。

您的模型中无效的方面似乎不是发送到您的操作方法的那些方面,而是来自数据库的那些方面。所以当模型绑定发生时,你有一个有效的对象,并且ModelState.IsValid是真的。但是当您尝试保存对象时,Entity Framework 仍会检测到它们无效并引发异常。

您会在实体上创建导致数据库中当前数据不正确的验证,这似乎很奇怪。考虑运行 SQL 脚本来更正数据库中的数据。

如果你不能这样做,你可以在将实体加载出数据库后尝试绑定它们:

var models = db.Model.Where(f => bar.Contains(f.Id)).ToList();
TryUpdateModel(models);
if(ModelState.IsValid)
{
    foreach(var model in models)
    {
        model.updated = true;
        db.Entry(model).State = EntityState.Modified;
    }
    db.SaveChanges();
}

当然,上面的代码只有在所有模型都有效的情况下才有效。如果您想有选择地只更新正确的,您可以检查ModelState.Errors属性是否存在与每个模型条目相关的错误。

如果您真的想在这种特殊情况下禁止实体验证,请记住这可能很危险,您可以在保存之前简单地禁用上下文验证。

db.Configuration.ValidateOnSaveEnabled = false;
于 2012-06-03T15:43:38.950 回答