Frage

Hat jemand Folgendes erlebt? Validierung von Objekten mit Feldern, die sich auf andere Entitäten beziehen sind besiedelt.

Das ist mir jetzt zweimal passiert und es scheint ein Problem mit faulen Laden zu sein, als ob das faule Laden die Antwort nicht schnell genug gegeben hätte.

Wir haben dieses (vereinfachte) Modell wo

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

Wenn wir einfach tun würden Context.Surveys.Single(id) oder Context.Surveys.Where(s => s.Id == id), wechseln Enabled Feld (oder ein anderes Feld) und machen a Context.SaveChanges() Es würde in 9 von 10 mal einen Validierungsfehler werfen, dass die OU Feld ist erforderlich und es ist nicht vorhanden.

Nach dem Hinzufügen .Include(s => s.OU) Dieses Problem wurde gelöst und ich dachte, dies sei das Ende. Obwohl gestern wieder ein ähnliches Problem mit dem folgenden Code gestoßen bin:

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

Dies würde ValidationErrors für Werte [4,5] während der Rückgabe Questions Bei der Inspektion durch den Debugger enthielt tatsächlich Fragen mit IdS 4 und 5. Wenn ich den Debugger einen Moment auf dem Pause machen würde if-datement Die Validierung würde danach korrekt durchlaufen.

Das Seltsame ist, dass ich diese Fehler zuvor (wissentlich) nicht erlebt habe und dass ich keine Bibliotheken oder Datenbanksoftware aktualisiert habe.

Diese Situation erschreckt mich ein wenig, da ich mich nicht darauf verlassen kann, dass ich immer wieder arbeitet. Oder mache ich etwas falsch?

Dies fühlt sich lose zu tun mit EF 4.1 Ladefilterte Kindersammlungen funktionieren nicht für viele zu viele zu viele Aber ich kann nicht erklären, wie dies hier zutreffen würde.

Update1: Die folgende Ausnahme würde nach den im ersten Beispiel angegebenen Schritten folgen:

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>

Der Code, um dies zu erreichen (nicht persönlich, sondern ein weiteres Team-Mitglied):

        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 ist ein Objekt, das die Post-Data vom Client enthält. survey.CanAdministrate(Context) Verwendet den Kontext, um den gesamten Baum der Organisationsinits aus der DB zu lesen, um die Rollen zu bestimmen.

War es hilfreich?

Lösung

Dies ist von Design und IMHO sehr gut. Der Kontext schaltet sich intern in einigen Operationen aus, und die Validierung ist einer davon. Dies ist Teil der internen Implementierung der Methode, die sie verursacht:

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

Warum ist es gut? Denn es vermeidet undichte faule Lasten für den Fall, wenn Sie sie nicht wollen. Übrigens. Wenn Sie die Validierungslogik für Eigenschaften platziert haben, die nicht geladen werden müssen, haben Sie es falsch gemacht. Es liegt in Ihrer Verantwortung, sicherzustellen, dass alle erforderlichen Eigenschaften vor der Validierung gefüllt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top