我有一个奇怪的问题。我有一个包含现有项目的数据库,我添加了一个新的验证规则,因此数据库中的某些项目不符合这个新规则。
我有一个循环找到一条记录,更改一个元素然后将其保存回数据库,如下所示:
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?
由于
答案 0 :(得分:3)
我认为您将ASP.NET MVC验证与Entity Framework的验证混淆。
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();
}
当然,只有模型的 all 有效时,上述代码才有效。如果要有选择地仅更新正确的属性,可以检查ModelState.Errors
属性是否存在与每个模型条目相关的错误。
如果你真的想在这种特殊情况下抑制实体验证,请记住这可能是危险的,你可以在保存前简单地禁用上下文验证。
db.Configuration.ValidateOnSaveEnabled = false;