Ich habe eine .NET4.0-Anwendung mit Entity Framework 5.0 und Sql Server CE 4.0.
Ich habe zwei Entitäten mit einer Eins-zu-Vielen-Beziehung (Eltern / Kind). Ich habe es so konfiguriert, dass es bei der Elterentfernung kaskadiert wird, aber aus irgendeinem Grund scheint es nicht zu funktionieren.
Hier ist eine vereinfachte Version meiner Entitäten:
%Vor%Die Verbindungszeichenfolge:
%Vor%Und eine vereinfachte Version des Workflows meiner App:
%Vor%Wenn ich versuche, die übergeordnete Entität zu löschen, wird Folgendes ausgelöst:
Die Beziehung konnte nicht geändert werden, weil einer oder mehrere der Fremdschlüsseleigenschaften sind nicht nullfähig. Wenn eine Änderung an a vorgenommen wird Beziehung, die zugehörige Fremdschlüsseleigenschaft wird auf einen Nullwert festgelegt. Wenn der Fremdschlüssel keine Nullwerte unterstützt, eine neue Beziehung muss definiert sein, die Fremdschlüsseleigenschaft muss eine andere zugewiesen werden Nicht-Null-Wert oder das nicht verwandte Objekt muss gelöscht werden.
Ich glaube, meine Beziehungskonfiguration ist in Ordnung ( folgte der Dokumentation ). Ich suchte auch nach Richtlinien zum Löschen gelöster Objekte .
Ich kann wirklich nicht verstehen, warum das Löschen nicht funktioniert. Ich möchte vermeiden, alle Kinder zu laden, sie einzeln zu löschen und sie das Elternteil zu löschen, weil es eine bessere Lösung als das geben muss.
Das Festlegen des Status einer Entität auf Deleted
und das Aufrufen von DbSet<T>.Remove
für diese Entität sind nicht identisch.
Der Unterschied besteht darin, dass das Setzen des Status nur den Status der Root-Entität (die in context.Entry
übergeben wird) in Deleted
ändert, aber nicht den Status verwandter Entitäten, während Remove
dies tut, wenn die Beziehung konfiguriert ist mit kaskadierendem Löschen.
Wenn Sie eine Ausnahme erhalten, hängt es tatsächlich davon ab, ob die Kinder (alle oder nur ein Teil) an den Kontext gebunden sind oder nicht. Dies führt zu einem Verhalten, das etwas schwierig zu folgen ist:
Remove
aufrufen, erhalten Sie keine Ausnahme, egal ob Kinder geladen sind oder nicht. Es gibt noch einen Unterschied:
DELETE
-Anweisung für jedes angefügte Kind und dann für das übergeordnete Element (weil Remove
alle als Deleted
markiert hat) DELETE
-Anweisung für das übergeordnete Element an die Datenbank, und da die kaskadierende Löschung aktiviert ist, löscht die Datenbank auch die untergeordneten Elemente. Deleted
setzen, können Sie möglicherweise eine Ausnahme erhalten:
Deleted
festgelegt, und EF beschwört, dass Sie versuchen, einen Prinzipal (die Stammentität) in einer erforderlichen Beziehung zu löschen, ohne die abhängigen Elemente (die untergeordneten Elemente) zu löschen. oder zumindest ohne ihre Fremdschlüssel auf eine andere Root-Entität zu setzen, die nicht in Deleted
state ist. Das ist die Ausnahme, die Sie hatten: account
ist der Stamm und user1
ist abhängig von account
und der Aufruf von context.Entry(account).State = EntityState.Deleted;
fügt auch user1
im Status Unchanged
an den Kontext an (oder ändert die Erkennung in SaveChanges
werde es tun, da bin ich mir nicht sicher. user1
ist Teil der account.Users
-Sammlung, weil das Relation Fixup es der Sammlung im ersten Kontext hinzugefügt hat, obwohl Sie es nicht explizit in Ihrem Code hinzugefügt haben. Deleted
eine DELETE
-Anweisung an die Datenbank senden, und erneutes kaskadierendes Löschen in der Datenbank wird auch die Kinder löschen. Dies funktioniert ohne Ausnahme. Ihr Code würde dann zum Beispiel funktionieren, wenn Sie account.Users = null
vor dem Setzen des Status auf Deleted
im zweiten Kontext oder vor dem Eintritt in den zweiten Kontext setzen. Meiner Meinung nach mit Remove
...
... ist eindeutig der bevorzugte Weg, da das Verhalten von Remove
viel mehr dem entspricht, was Sie für eine erforderliche Beziehung mit kaskadierendem Löschen erwarten würden (was in Ihrem Modell der Fall ist). Die Abhängigkeit des Verhaltens einer manuellen Statusänderung von Zuständen anderer Entitäten macht die Verwendung schwieriger. Ich würde es als fortgeschrittene Verwendung nur für spezielle Fälle betrachten.
Der Unterschied ist nicht allgemein bekannt oder dokumentiert. Ich habe sehr wenige Beiträge darüber gesehen. Das einzige, das ich jetzt wieder finden konnte, ist dieses von Zeeshan Hirani .
Ich habe einen etwas anderen Ansatz versucht und seltsamerweise hat es funktioniert. Wenn ich diesen Code ersetze:
%Vor%Durch diesen:
%Vor%Es funktioniert ohne weitere Probleme. Ich bin mir nicht sicher, ob das ein Fehler ist oder ob mir etwas fehlt. Ich würde wirklich etwas Licht über die Angelegenheit schätzen, weil ich ziemlich sicher war, dass der erste Weg (EntityState.Deleted) der empfohlene war.
Tags und Links entity-framework entity-framework-5 .net-4.0 sql-server-ce