有人遇到以下情况吗?使用引用其他实体的字段验证对象会引发错误,指出该字段不存在,并且当您调试程序时,您将检查实体 填充的字段。< / p>
现在两次发生这种事情,似乎是延迟加载的一些问题,好像延迟加载没有给出足够快的答案。
我们有这个(简化)模型
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时间抛出一个验证错误,即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]的ValidationErrors,而Questions
通过调试器检查时确实包含Id
s 4和5的问题。如果我暂停调试器{ {1}} - 声明验证将在之后正确进行。
奇怪的是,我之前没有(明知)遇到过这些错误,而且我没有更新任何库或数据库软件。
这种情况让我感到害怕,因为我似乎不能依赖Lazy Loading来始终工作。或者也许我做错了什么?
这与EF 4.1 loading filtered child collections not working for many-to-many松散相关,但我无法解释这在这里是如何适用的。
UPDATE1 : 按照第一个示例中提供的步骤弹出以下异常:
if
实现此目的的代码(不是由我个人编写,而是由另一个团队成员编写):
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
使用Context从DB中读取整个OrganisationalUnits树以确定角色。
答案 0 :(得分: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;
}
为什么好?因为它可以避免在您不需要它们时泄漏延迟负载。顺便说一句。如果您将验证逻辑放在不必加载的属性上,那么您就错了。您有责任确保在验证之前填写所有必要的属性。