Question

Avez quelqu'un d'expérience qui suit? Objets avec des champs Validation qui se réfèrent à d'autres entités te jetterais une erreur indiquant que le champ était pas présent et que lorsque vous déboguer le programme et vous inspecter les entités que les champs sont population.

Ce qui est arrivé à moi à deux reprises maintenant et il semble y avoir un problème avec le chargement paresseux, comme si le chargement paresseux n'a pas donné la réponse assez vite.

Nous avons ce modèle (simplifié) où

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

Si nous voulons juste faire Context.Surveys.Single(id) ou Context.Surveys.Where(s => s.Id == id), changer le champ Enabled (ou tout autre domaine), et faire un Context.SaveChanges() il le ferait dans 9 fois sur 10 jeter une erreur de validation que le champ OU est nécessaire et que ce n'est pas présent .

Après avoir ajouté .Include(s => s.OU) ce problème a été résolu et je pensais que ce fut la fin de celui-ci. Bien que hier encore, je rencontre un problème similaire avec le code suivant:

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

retournerait validationErrors pour les valeurs [4,5] tandis que Questions lors de l'inspection par le débogueur des questions bien contenues avec Ids 4 et 5. Si je mettre en pause le débogueur un moment sur la if-déclaration de la validation passerait par la suite correctement .

La chose étrange est que je ne l'ai pas (sciemment) l'expérience de ces erreurs avant et que je ne mettre à jour des bibliothèques ou des logiciels de base de données.

Cette situation me fait peur un peu comme il semble que je ne peux pas compter sur le chargement paresseux pour toujours du travail. Ou peut-être que je fais quelque chose de mal?

Cela se sent vaguement lié à EF 4.1 collections enfant filtré de chargement ne fonctionne pas pour beaucoup à de nombreux mais je ne peux pas expliquer comment cela s'appliquerait ici.

Update1 : L'exception suivante serait en suivant les apparaitre étapes prévues dans le premier exemple:

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>

Le code pour y parvenir (non écrit par moi personnellement, mais une autre membre de l'équipe):

        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 est un objet contenant les données de post-du client. survey.CanAdministrate(Context) utilise le contexte pour lire tout l'arbre de OrganisationalUnits de la DB pour déterminer les rôles.

Était-ce utile?

La solution

Ceci est par la conception et à mon avis, il est très bon point. Contexte interne se charge de paresseux dans certaines opérations et de validation est l'un d'entre eux. Cela fait partie de la mise en œuvre interne de la méthode qu'elle provoque:

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

Pourquoi est-il bon? Parce qu'il évite les charges paresseux qui fuient dans le cas où vous ne voulez pas. BTW. si vous avez placé la logique de validation sur la propriété qui ne doit pas être chargé vous l'avez fait mal. Il vous incombe de veiller à ce que toutes les propriétés nécessaires sont remplies avant la validation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top