Ich habe ein Eintrags-Entfernungsproblem mit dem EntityFramework und eine Viele-zu-Viele-Beziehung für dieselbe Entität. Betrachten Sie dieses einfache Beispiel:
Entität:
%Vor%Fließende API-Konfiguration:
%Vor%Cascade Delete
in der Fluent API zu definieren? Wie löscht man am besten UserEntity
, zum Beispiel Foo
?
Er sucht jetzt nach mir, ich muss Clear
die Foo
s Friends
Sammlung, dann muss ich alle anderen UserEntities
laden, die Foo
in Friends
enthalten, und dann entfernen Foo
aus jeder Liste, bevor ich Foo
von Users
entferne. Aber es klingt zu kompliziert.
Ist es möglich direkt auf die relationale Tabelle zuzugreifen, damit ich solche Einträge entfernen kann
%Vor%Danke!
Update01:
Meine beste Lösung für dieses Problem besteht darin, die rohe SQL-Anweisung auszuführen, bevor ich SaveChanges
:
Aber der Nachteil davon ist, dass, wenn SaveChanges
aus irgendeinem Grund fehlschlägt, die FriendshipRelation
bereits entfernt sind und nicht zurückgerollt werden konnten. Oder irre ich mich?
Die Antwort ist ganz einfach:
Entity Framework kann Kaskadenlöschung nicht definieren, wenn es nicht weiß, welche Eigenschaften zu der Beziehung gehören.
Zusätzlich gibt es in einer Viele: Viele Beziehung eine dritte Tabelle, die für die Verwaltung der Beziehung zuständig ist. Diese Tabelle muss mindestens 2 FKs haben. Sie sollten die Kaskadenlöschung für jede FK konfigurieren, nicht für die "gesamte Tabelle".
Die Lösung besteht darin, die Entität FriendshipRelation
zu erstellen. So:
Nun musst du UserEntity
ändern. Anstelle einer Sammlung von UserEntity
hat es eine Sammlung von UserFriendship
. So:
Sehen wir uns das Mapping an:
%Vor%Generierte Migration:
%Vor%Um alle Freunde des Benutzers abzurufen:
%Vor% All das funktioniert gut. Es gibt jedoch ein Problem bei der Zuordnung (was auch in Ihrem aktuellen Mapping passiert). Angenommen, "I" ist ein UserEntity
:
Wenn ich meine Eigenschaft Friends
abrufe, wird "John", "Ann", aber nicht "Richard" zurückgegeben. Warum? weil Richard der "Maker" der Beziehung ist, nicht ich. Die Eigenschaft Friends
ist nur an eine Seite der Beziehung gebunden.
Ok. Wie kann ich das lösen? Einfach! Ändere deine UserEntity
-Klasse:
Aktualisieren Sie das Mapping:
%Vor%Es sind keine Migrationen notwendig.
Um alle Freunde des Benutzers abzurufen:
%Vor%Ja, Sie müssen die Sammlung iterieren und alle untergeordneten Objekte entfernen. Sehen Sie meine Antwort in diesem Thread Saubere Aktualisierung einer Hierarchie in Entity Framework
Nach meiner Antwort erstellen Sie einfach ein UserFriendship
dbset:
Jetzt können Sie alle Freunde einer bestimmten Benutzer-ID abrufen, löschen Sie alle auf einmal und entfernen Sie den Benutzer.
Ja, das ist möglich. Sie haben jetzt ein UserFriendship
dbset.
Ich hoffe, es hilft!
1) Ich sehe keinen direkten Weg, um die Kaskade der Viele-zu-Viele-Beziehungen mit FluentApi zu kontrollieren.
2) Die einzige verfügbare Möglichkeit, die ich kontrollieren kann, ist die Verwendung von ManyToManyCascadeDeleteConvention
, was meiner Meinung nach standardmäßig aktiviert ist, zumindest für mich. Ich habe gerade eine meiner Migrationen überprüft, einschließlich einer Viele-zu-Viele-Beziehung, und tatsächlich ist die cascadeDelete: true
für beide Schlüssel vorhanden.
BEARBEITEN: Entschuldigung, ich habe gerade festgestellt, dass die ManyToManyCascadeDeleteConvention
den Fall der Selbstreferenzierung nicht abdeckt. Diese verwandte Frage lautet, dass
Sie erhalten diese Fehlermeldung, da eine Tabelle in SQL Server nicht mehr als einmal in einer Liste aller kaskadierenden referenziellen Aktionen angezeigt werden kann, die entweder durch eine DELETE- oder eine UPDATE-Anweisung gestartet werden. Beispielsweise muss der Baum der kaskadierenden referenziellen Aktionen nur einen Pfad zu einer bestimmten Tabelle in der kaskadierenden referenziellen Aktionsstruktur haben.
Sie müssen also einen benutzerdefinierten Löschcode haben (wie den sql-Befehl, den Sie bereits haben) und ihn in einem Transaktionsumfang .
3) Sie sollten nicht aus dem Kontext auf diese Tabelle zugreifen können. Normalerweise ist die durch eine Viele-zu-Viele-Beziehung erzeugte Tabelle ein Nebenprodukt der Implementierung in einem relationalen DBMS und wird als eine schwache Tabelle entsprechend der zugehörigen Tabellen betrachtet, was bedeutet, dass ihre Zeilen sein sollten kaskadengelöscht, wenn eine der zugehörigen Entitäten entfernt wird.
Ich rate Ihnen zunächst, zu überprüfen, ob Ihre Migration die Fremdschlüssel für Tabellen auf das Löschen in Kaskade setzt. Wenn Sie dann aus irgendeinem Grund die Löschung eines Datensatzes mit zugehörigen Datensätzen in der Viele-zu-Viele-Beziehung einschränken müssen, dann suchen Sie in Ihren Transaktionen einfach danach.
4) Wenn Sie das wirklich möchten (FluentApi aktiviert standardmäßig ManyToManyCascadeDeleteConvention
), müssen Sie den Befehl sql und Ihre SaveChanges in einen Transaktionsbereich einschließen.
Tags und Links c# entity-framework entity-framework-6 ef-code-first code-first