2011-09-05 34 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

也许在其他情况下,您已加载或初始化导航属性。 –