不准时延迟 /递延链接加载?
-
25-10-2019 - |
题
有人遇到以下内容吗?用指称其他实体的字段验证对象会给您带来一个错误,说明该字段不存在,并且当您调试程序时,您将检查字段的实体 是 人口稠密。
这已经发生了两次,我已经发生了两次,懒惰负载似乎有些问题,好像懒惰的负载没有足够快地给答案。
我们有这个(简化的)模型
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分的9次中,验证错误是 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));
}
}
}
这将返回值[4,5]的验证验证者 Questions
经过调试器检查,确实包含了与 Id
S 4和5。如果我暂停调试器 if
- 陈述验证将在之后正确进行。
奇怪的是,我以前没有(故意)遇到这些错误,也没有更新任何库或数据库软件。
这种情况使我有些恐惧,因为我似乎不能依靠懒惰的加载来始终工作。也许我做错了什么?
这感觉与 EF 4.1加载过滤的儿童收集不适用于多个人 但是我无法解释这将如何适用。
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
是一个包含客户端的DATA的对象。 survey.CanAdministrate(Context)
使用上下文读取来自DB的整个组织原子树以确定角色。
解决方案
这是设计,恕我直言,这是非常好的功能。上下文内部关闭某些操作中的懒惰加载,验证是其中之一。这是导致该方法的内部实施的一部分:
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;
}
为什么好吗?因为如果您不想要它们,它会避免泄漏的懒惰负载。顺便提一句。如果您将验证逻辑放在不必加载的属性上,则您做错了。您有责任确保在验证之前填写所有必要的属性。