2011-09-05 75 views
1

有人遇到以下情況嗎?使用引用其他實體的字段驗證對象會引發錯誤,指出該字段不存在,並且在調試程序時您將檢查填充字段的實體。延遲加載鏈接不及時?

這兩次發生在我身上,似乎是延遲加載的一些問題,就好像延遲加載沒有給出足夠快的答案。

我們有這個(簡化)模型,其中

class Survey { 
    ... 
    public bool Enabled {get; set;} 
    [Required] 
    public virtual OrganisationalUnit OU {get; set;} 
    ... 
} 

如果我們只是做Context.Surveys.Single(id)Context.Surveys.Where(s => s.Id == id),改變Enabled場(或任何其他字段),並做了Context.SaveChanges()它會在出9 10次拋出驗證錯誤,OU字段是必需的,它不存在。

添加.Include(s => s.OU)後,此問題已解決,我認爲這是它的結束。雖然昨天我又遇到了類似的問題,用下面的代碼:

public class SurveyQuestionMultipleChoiceMultiSelect : SurveyQuestionMultipleChoice 
{ 
    public override IEnumerable<ValidationResult> validateValue(string _, IEnumerable<string> values) 
    { 
     int ivalue; 
     foreach(string value in values) { 

      bool success = int.TryParse(value, out ivalue); 

      if (!success || !Questions.Any(q => q.Id == ivalue)) 
       yield return new ValidationResult(String.Format(GUI.error_multiplechoice_answer_not_element_of, ivalue)); 
     } 
    } 
} 

這將通過調試經檢查返回ValidationErrors的值[4,5],而Questions確實包含有Id第4和5。如果我的問題會在if -statement上暫停調試程序,之後驗證將正確進行。

奇怪的是,我沒有(明知)之前遇到這些錯誤,並且我沒有更新任何庫或數據庫軟件。

這種情況讓我有點害怕,因爲看起來我不能依賴Lazy Loading來始終工作。或者,也許我做錯了什麼?

這種感覺與EF 4.1 loading filtered child collections not working for many-to-many鬆散相關,但我無法解釋這將如何應用於此。

UPDATE1: 以下異常將按照第一個例子中提供的步驟彈出:

System.Data.Entity.Validation.DbEntityValidationException was unhandled by user code 
    Message=Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. 
    Source=EntityFramework 
    StackTrace: 
     at System.Data.Entity.Internal.InternalContext.SaveChanges() 
     at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() 
     at System.Data.Entity.DbContext.SaveChanges() 
     at Caracal.Application.Controllers.SurveyController.BulkEnable(SurveyBulkAction data) in C:\Users\Alessandro\Caracal\DigEvalProject\trunk\Caracal\application\Controllers\SurveyController.cs:line 353 
     at lambda_method(Closure , ControllerBase , Object[]) 
     at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) 
     at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) 
     at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) 
     at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() 
     at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) 
    InnerException: 
    <really-empty> 

的代碼來實現這一目標(不是由我親自寫的,但另一個團隊成員):

 bool option = data.option == "true"; 

     // Check if all surveys can be set to the enabled state 
     foreach (int id in data.surveys) 
     { 
      Survey survey = Context.Surveys.SingleOrDefault(s => s.Id == id); 
      if (survey == null || !survey.CanAdministrate(Context)) 
       return JsonResponse.Error(GUI.survey_enable_change_bulk_failed); 

      surveys.Add(survey); 
     } 

     // Enable/disable the selected surveys. 
     foreach (Survey survey in surveys) 
      survey.Enabled = option; 

     Context.SaveChanges(); 

data是包含來自客戶端的數據後的對象。 survey.CanAdministrate(Context)使用上下文從數據庫中讀取整個OrganisationalUnits樹來確定角色。

+1

請包括1。異常類型和消息,2.示例代碼,顯示如何管理ObjectContext。 – Richard

+0

我已經添加了這個異常,但是你想知道在2中究竟是什麼?代碼中的步驟是爲了得到這個錯誤嗎? –

回答

3

這是由設計和恕我直言,這是非常好的功能。 Context在內部關閉了一些操作中的延遲加載,並且驗證就是其中之一。這是導致它的內部實現的一部分:

public virtual DbEntityValidationResult GetValidationResult(IDictionary<object, object> items) 
{ 
    EntityValidator entityValidator = 
     this.InternalContext.ValidationProvider.GetEntityValidator(this); 
    bool lazyLoadingEnabled = this.InternalContext.LazyLoadingEnabled; 
    this.InternalContext.LazyLoadingEnabled = false; 
    DbEntityValidationResult result = null; 
    try 
    { 
     ... 
    } 
    finally 
    { 
     this.InternalContext.LazyLoadingEnabled = lazyLoadingEnabled; 
    } 
    return result; 
} 

爲什麼它是好的?因爲它可以避免在不需要它們的情況下發生泄漏延遲加載。順便說一句。如果你將屬性上的驗證邏輯放在了不需要加載的地方,那麼你做錯了。您有責任確保在驗證之前填寫所有必要的屬性。

+0

這確實是我的問題的一個很好的答案和解釋。但是,你能告訴我爲什麼只發生在9/10例中嗎? (也就是說,不是總是,我真的沒有計算出現次數。) –

+1

也許在其他情況下,您已加載或初始化導航屬性。 –