Вопрос

Кто -то испытал следующее? Проверка объектов с полями, которые ссылаются на другие сущности, принесло бы вам ошибку, в которой указано, что поле не присутствовало и что когда вы отлаживаете программу, и вы осматриваете объекты, которые поля находятся Заполнен.

Это случилось со мной в два раза, и это кажется какой -то проблемой с ленивой загрузкой, как будто ленивая нагрузка не дала ответа достаточно быстро.

У нас есть (упрощенная) модель, где

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

Это вернет валидации для значений [4,5], пока Questions После проверки через отладчик действительно содержал вопросы с IdS 4 и 5. Если бы я сделал паузу отладчика на момент if-Поджнение Проверка пройдет правильно после этого.

Странно то, что я раньше не испытывал эти ошибки и что я не обновлял никаких библиотек или программного обеспечения для базы данных.

Эта ситуация немного путает меня, так как кажется, что я не могу полагаться на ленивую нагрузку, чтобы всегда работать. Или, может быть, я что -то не так делаю?

Это чувствует себя слабо связанным с EF 4.1. Загрузка отфильтрованных дочерних коллекций не работает для многих к многим Но я не могу объяснить, как это будет применить здесь.

Обновление1: Следующее исключение будет всплыть, выполнив шаги, представленные в первом примере:

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) использует контекст для чтения всего дерева организма из БД для определения ролей.

Это было полезно?

Решение

Это по дизайну, и ИМХО это очень хорошая функция. Контекст внутренне отключает ленивую загрузку в некоторых операциях, и валидация является одной из них. Это является частью внутренней реализации метода, который его вызывает:

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

Почему это хорошо? Потому что это избегает протекающих ленивых нагрузок, если вы не хотите их. Кстати. Если вы разместили логику проверки на свойство, которое не нужно загружать, вы сделали это неправильно. Вы обязаны обеспечить заполнение всех необходимых свойств до проверки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top