Entity Framework fügt untergeordnete Objekte in der falschen Reihenfolge ein

8

Frage

Warum fügt EF zuerst ein untergeordnetes Objekt (PersonalWorkRecord) mit einer Abhängigkeit vor dem Objekt ein, von dem es abhängig ist (TimesheetActivity)? Was sind meine Möglichkeiten, dies zu korrigieren?

ERD (vereinfacht)

Dies ist durch ein anderes System außerhalb meiner direkten Kontrolle vordefiniert.

EF Setup und Code speichern

Ich bin mir nicht sicher, warum ich / wie Entity Framework die Objekte, die ich habe, in der Reihenfolge einfüge, in der es ist, aber hier ist der Code, den ich verwende, um ein Elternteil und mehrere Kinder einzufügen.

%Vor%

SQL-Trace der EF-Inserts

Wenn ich den Code ausführe, erhalte ich eine SQL-Fremdschlüsselverletzung im PersonalityWorkRecord (TimesheetActivityID), weil ich die Aktivität noch nicht hinzugefügt habe (siehe Trace).

%Vor%

Datenzusammenfassung

%Vor%

Untergeordnete Objekte entfernen

Hier ist der Code für die Kindobjektmethode. Ich habe diese Methode hinzugefügt, um die Objekte aus den Objekten der Zeiterfassungsobjekte zu entfernen, die keine Fremdschlüssel sind. Zum Beispiel habe ich ein Crew-Objekt, aber ich habe auch einen CrewID-Fremdschlüssel, also habe ich Crew = null gesetzt, damit EF nicht versucht, es einzufügen, da es bereits existiert.

%Vor%

Debuggen von Werten vor EF-Sicherung

Nach meinem Verständnis wird ein dbContex.ObjectNameHere.Local hinzugefügt / geändert / gelöscht, wenn ein dbContext.Save () aufgerufen wird. (Abhängig davon, was der Entitätsstatus auch eingestellt ist.) Hier ist, was EF versucht, zu speichern, bevor ich die save () -Funktion aufruft und eine SQL-FK-Ausnahme erhalte. Dann bekomme ich die FK-Ausnahme.

  

Die INSERT-Anweisung steht im Konflikt mit der FOREIGN KEY-Einschränkung   "FK_PersonnelWorkRecords_TimesheetActivities". Der Konflikt ist aufgetreten   in der Datenbank "VPMTEST_GC", Tabelle "dbo.TimesheetActivities", Spalte   'ArbeitszeittabelleAktivitätID'. Die Anweisung wurde beendet.

Notizen

Bitte lassen Sie es mich wissen, wenn ich etwas schreiben kann, um meine Frage zu beschreiben. Ich habe mich in google / SO nach Antworten umgesehen, aber bis jetzt keine solide Antworten, sieht es so aus, als ob EF die Reihenfolge des Einfügens von Objekten nicht bestimmen kann, wenn das Domänenmodell nicht anders eingerichtet ist? Ich bin nicht in der Lage, die Struktur der meisten Objekte zu ändern, wie sie von einem anderen System verwendet werden. Ich kann versuchen, meinen EF-Aufruf zu ändern, ich würde es vorziehen, Raw SQL nicht zu verwenden, da die Objekte ziemlich viel umfangreicher sind als die vereinfachten Versionen, die ich hier gepostet habe.

Ähnliche Fragen: Selbstreferenzierende Entität und Reihenfolge einfügen

    
Gram 19.02.2014, 01:45
quelle

2 Antworten

1

In Ihrer RemoveChildObjects Methode sehe ich die Zeile ...

%Vor%

Sie haben also offensichtlich die Eigenschaft der inversen Navigation von Timesheet.TimesheetActivities auf null gesetzt. Machst du dasselbe mit PersonnelWorkRecord.TimesheetActivity und PersonnelWorkRecord.PersonnelWorkday , d. H. Setzt du diese Eigenschaften auch in den geschachtelten null Methoden auf RemoveChildObjects ?

Dies könnte ein Problem sein, weil Sie zwei verschiedene Pfade von Timesheet bis PersonnelWorkRecord haben, nämlich:

%Vor%

Beim Aufruf von db.Timesheets.Add(timesheet) glaube ich, dass EF jede Verzweigung im Objektgraphen einzeln durchläuft und auf dem Pfad bestimmt, welche zusammenhängenden Objekte ("Knoten") abhängig sind und welche in einer Beziehung die Reihenfolge bestimmen Einfügen. timesheet selbst ist Principal für alle seine Beziehungen, daher ist es klar, dass es zuerst eingefügt werden muss. Dann beginnt EF, durch eine der Sammlungen Timesheet.TimesheetActivities oder Timesheet.PersonnelWorkdays zu iterieren. Wer zuerst kommt, spielt keine Rolle. Scheinbar startet EF mit Timesheet.PersonnelWorkdays . (Es würde das Problem nicht lösen, wenn es mit Timesheet.TimesheetActivities beginnen würde, Sie würden die gleiche Ausnahme bekommen, aber mit PersonnelWorkRecord.PersonnelWorkday anstelle von PersonnelWorkRecord.TimesheetActivity .)% Co_de% hängt nur von PersonnelWorkday ab, das bereits eingefügt wurde. Also, Timesheet kann ebenfalls eingefügt werden.

Dann fährt EF mit PersonnelWorkday weiter. In Bezug auf die PersonnelWorkday.PersonnelWorkRecords Abhängigkeit von PersonnelWorkday gibt es wieder kein Problem, da die PersonnelWorkRecord bereits vorher eingefügt wurde. Aber wenn EF die PersonnelWorkday Abhängigkeit von TimesheetActivity entdeckt, wird es sehen, dass diese PersonnelWorkRecord TimesheetActivity ist (weil du sie auf null gesetzt hast). Es wird nun vorausgesetzt, dass die Abhängigkeit durch die Fremdschlüsseleigenschaft null alone beschrieben wird, die sich auf einen bestehenden Datensatz beziehen muss. Es fügt das TimesheetActivityID ein und dies verletzt eine Fremdschlüsseleinschränkung.

Wenn PersonnelWorkRecord nicht PersonnelWorkRecord.TimesheetActivity ist, würde EF feststellen, dass dieses Objekt noch nicht eingefügt wurde, aber es ist das Prinzipal für null . So kann es feststellen, dass diese PersonnelWorkRecord eingefügt werden muss vor die TimesheetActivity .

Ich würde hoffen, dass Ihr Code funktioniert, wenn Sie die Eigenschaften für die inverse Navigation nicht auf PersonnelWorkRecord festlegen - oder zumindest nicht auf die beiden Navigationseigenschaften in null . (Das Setzen der anderen Navigationseigenschaften wie PersonnelWorkRecord , tsa.Creator usw. auf tsa.Facility sollte kein Problem darstellen, da diese verwandten Objekte tatsächlich bereits in der Datenbank vorhanden sind und Sie die korrekten FK-Eigenschaftswerte für diese Objekte festgelegt haben.)

    
Slauma 19.02.2014, 21:16
quelle
0

Dies ist möglicherweise nicht mehr gültig, aber ist es eine Option, eine Transaktion zu verwenden und jedes untergeordnete Objekt einzeln hinzuzufügen?

Hinweis: Ich denke, dass die Lösung von Slauma vollständiger ist, ein Transaktionsanruf kann jedoch immer noch eine Option für andere sein, die ähnliche Probleme haben.

    
Mist 19.02.2014 22:44
quelle