2012-06-03 54 views
1

我遇到了一個奇怪的問題。我有一個包含現有項目的數據庫,我添加了一個新的驗證規則,因此數據庫中的某些項目不符合此新規則。Foreach循環中的實體驗證,如果驗證失敗,它將在下一個循環中保持失敗

我有一個循環,發現一個記錄,改變一個元素然後將其保存到數據庫中,這樣的:

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(); 
     } 
    } 
} 

這也trows一個驗證失敗的異常,我猜是因爲在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

你用'for'循環檢查嗎? – Damith

+0

現在有和同樣的問題。 –

回答

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; 
+0

感謝您的信息,有沒有辦法改變實體的行爲,不檢查在這個特定的部分驗證? –

+0

@GarrettFogerlie:請參閱http://stackoverflow.com/questions/8099949/entity-framework-mvc3-temporarily-disable-validation – StriplingWarrior

+0

非常感謝,在保存更改之前添加了'db.Configuration.ValidateOnSaveEnabled = false;' 。將此添加到您的答案中,我會接受它。我無法更新現有數據庫信息的原因是因爲它是一個是或否的答案,它同意從一開始就應該要求的條款。謝謝! –