7

Ich habe diesen Code in einem Windows-Service 4.5 auf .NET gezielt, die eine Datenbank-first Entity Framework Schicht verwendet:Warum fügt Entity Framework untergeordnete Elemente ein, wenn ich das übergeordnete Element aktualisiere?

var existingState = DataProcessor.GetProcessState(workerId); 

existingState.ProcessStatusTypeId = (int)status; 
existingState.PercentProgress = percentProgress; 
existingState.ProgressLog = log; 

DataProcessor.UpdateProcessState(existingState); 

Und diesen Code in einer Datenverarbeitungsklasse in der gleichen Lösung:

public ProcessState GetProcessState(int id) 
{ 
    using (var context = new TaskManagerEntities()) 
    { 
     var processes = (from p in context.ProcessStates.Include("ProcessType").Include("ProcessStatusType") 
         where p.IsActive && p.ProcessStateId == id 
         select p); 

     return processes.FirstOrDefault(); 
    } 
} 

public ProcessState UpdateProcessState(ProcessState processState) 
{ 
    using (var context = new TaskManagerEntities()) 
    { 
     context.ProcessStates.Add(processState); 
     context.Entry(processState).State = System.Data.EntityState.Modified; 
     context.SaveChanges(); 
    } 

    return processState; 
} 

ProcessState ist ein Elternteil für zwei andere Klassen, ProcessStatusType und ProcessType. Wenn ich diesen Code im Windows-Dienst ausführe, ruft er einen Datensatz ab, aktualisiert die Entität und speichert sie. Ungeachtet der Tatsache, dass das untergeordnete ProcessType-Kind in dem obigen Code nie verwendet wird, führt EF bei der Ausführung der Speicherung der ProcessState-Entität eine Einfügung in die ProcessType-Tabelle durch und erstellt darin einen neuen Datensatz. Dann ändert es den FK in der ProcessStatus-Entität, um es auf das neue Kind zu verweisen, und speichert es in der Datenbank.

Es tut nicht tun dies in der Tabelle ProcessStatusType, die mit einer im Wesentlichen identisch FK Eltern-Kind-Beziehung eingerichtet ist.

Ich habe jetzt eine Datenbank voller identischer ProcessType-Einträge, die ich nicht brauche, und ich weiß nicht, warum dies auftritt. Ich habe das Gefühl, dass ich einen offensichtlichen Fehler mache, den ich nicht sehen kann, weil dies mein erstes EF-Projekt ist. Ist das Problem, dass ich den Kontext zwischen Anrufen ablaufen lasse, aber die gleiche Entität beibehalten?

+1

Überprüfen Sie, ob das zu ladende ProcessType-Objekt die Eigenschaft für den Primärschlüssel der Tabelle hat und korrekt ausgefüllt ist. Wenn zum Beispiel'ProcessType.Id = 0 ', wird EF denken, dass es ein neues Objekt ist, und es einfügen –

+0

Ich habe gerade überprüft, und es tut. Der Primärschlüssel ist auf dem Weg vorhanden und korrekt und wird auf den Primärschlüssel des neuen Datenbankeintrags gesetzt, wenn er herauskommt. – RedBrogdon

Antwort

5

Mit Add wird der Status aller Elemente auf Added gesetzt, wodurch die untergeordneten Elemente eingefügt werden. Das übergeordnete Element wird nicht eingefügt, wenn Sie EntityState.Modified für dieses Element angeben.

Verwenden Sie die folgenden in UpdateProcessState lieber als Hinzufügen verwenden.

context.ProcessStates.Attach(processState); 
context.Entry(processState).State = EntityState.Modified; 
context.SaveChanges(); 

Attach gesetzt sollte den Status aller Elemente unverändert und durch die Angabe für das übergeordnete Element Modified Sie an, dass nur dieses Element aktualisiert werden.

Auf eine andere Anmerkung. Sie sollten den stark typisierten Include(x => x.ProcessType) statt Include("ProcessType") verwenden.

+0

Danke für die Hilfe. Das Attach/Add-Problem verursachte das Problem. Ich habe diese Veränderung gemacht, und jetzt läuft alles richtig. In Bezug auf die stark typisierten Include-Anweisungen, sind diese in EF5 noch verfügbar? Mein Compiler wirft einen Fehler auf sie, und ich sah diesen Beitrag: http://stackoverflow.com/questions/4544756/using-include-in-entity-framework-4-with-lambda-expressions, die darauf hindeutet, dass sie sind veraltet. – RedBrogdon

+1

Ja, das stark typisierte Include wird unterstützt http://msdn.microsoft.com/en-us/library/gg671236(VS.103).aspx. Versuchen Sie, eine Verwendung von System.Data.Entity hinzuzufügen, damit der Compiler aufhört, sich zu beschweren. – Martin4ndersen

+0

Und da sind sie. Danke noch einmal. Interessant, dass Intellisense die Verwendung von Anweisungen für unimported-but-available-in-referred-Assembly-Methoden vorschlägt, aber nicht, wenn sie Polymorphe von etwas sind, das sich bereits in Ihren Namespaces befindet. – RedBrogdon

Verwandte Themen