Ich habe ein Problem, wenn ich versuche, meinen Tabellen Einschränkungen hinzuzufügen. Ich bekomme den Fehler:
Die Einführung der FOREIGN KEY-Einschränkung 'FK74988DB24B3C886' in Tabelle 'Employee' kann zu Zyklen oder mehreren Kaskadenpfaden führen. Geben Sie ON DELETE NO ACTION oder ON UPDATE NO ACTION an oder ändern Sie andere FOREIGN KEY-Einschränkungen.
Meine Einschränkung liegt zwischen einer Code
Tabelle und einer employee
Tabelle. Die Code
Tabelle enthält Id
, Name
, FriendlyName
, Type
und ein Value
. Das employee
hat eine Reihe von Feldern, die auf Codes verweisen, so dass es für jeden Codetyp eine Referenz geben kann.
Ich muss die Felder auf null setzen, wenn der Code, auf den verwiesen wird, gelöscht wird.
Irgendwelche Ideen, wie ich das machen kann?
quelle
Antworten:
SQL Server zählt einfach Kaskadenpfade und versucht nicht herauszufinden, ob tatsächlich Zyklen vorhanden sind, sondern nimmt das Schlimmste an und weigert sich, die referenziellen Aktionen (CASCADE) zu erstellen: Sie können und sollten die Einschränkungen auch ohne die referenziellen Aktionen erstellen. Wenn Sie Ihr Design nicht ändern können (oder dies die Dinge gefährden würde), sollten Sie in Betracht ziehen, Trigger als letzten Ausweg zu verwenden.
Das Auflösen von Kaskadenpfaden durch FWIW ist ein komplexes Problem. Andere SQL-Produkte ignorieren das Problem einfach und ermöglichen es Ihnen, Zyklen zu erstellen. In diesem Fall ist es ein Wettlauf, zu sehen, welche den Wert zuletzt überschreiben, wahrscheinlich aus Unwissenheit des Designers (z. B. ACE / Jet tut dies). Ich verstehe, dass einige SQL-Produkte versuchen werden, einfache Fälle zu lösen. Tatsache bleibt, SQL Server versucht es nicht einmal, geht auf Nummer sicher, indem mehr als ein Pfad nicht zugelassen wird, und zumindest sagt es Ihnen dies.
Microsoft selbst empfiehlt die Verwendung von Triggern anstelle von FK-Einschränkungen.
quelle
Eine typische Situation mit mehreren Kaskadenpfaden ist folgende: Eine Mastertabelle mit zwei Details, beispielsweise "Master" und "Detail1" und "Detail2". Beide Details werden kaskadiert gelöscht. Bisher keine Probleme. Was aber, wenn beide Details eine Eins-zu-Viele-Beziehung zu einer anderen Tabelle haben (sagen Sie "SomeOtherTable")? SomeOtherTable hat eine Detail1ID-Spalte UND eine Detail2ID-Spalte.
Mit anderen Worten: Einige der Datensätze in SomeOtherTable sind mit Detail1-Datensätzen verknüpft, und einige der Datensätze in SomeOtherTable sind mit Detail2-Datensätzen verknüpft. Selbst wenn garantiert ist, dass SomeOtherTable-Datensätze niemals zu beiden Details gehören, ist es jetzt unmöglich, die Datensätze von SomeOhterTable für beide Details zu kaskadieren, da es mehrere Kaskadenpfade von Master zu SomeOtherTable gibt (einen über Detail1 und einen über Detail2). Jetzt haben Sie das vielleicht schon verstanden. Hier ist eine mögliche Lösung:
Alle ID-Felder sind Schlüsselfelder und werden automatisch erhöht. Der Kern liegt in den DetailMainId-Feldern der Detailtabellen. Diese Felder sind sowohl Schlüssel- als auch Referenzkontraint. Es ist jetzt möglich, alles kaskadiert zu löschen, indem nur Stammsätze gelöscht werden. Der Nachteil ist, dass für jeden Detail1-Datensatz UND für jeden Detail2-Datensatz auch ein DetailMain-Datensatz vorhanden sein muss (der tatsächlich zuerst erstellt wird, um die richtige und eindeutige ID zu erhalten).
quelle
Ich möchte darauf hinweisen, dass es (funktional) einen GROSSEN Unterschied zwischen Zyklen und / oder mehreren Pfaden im SCHEMA und in den DATEN gibt. Während Zyklen und möglicherweise Mehrwege in den DATEN die Verarbeitung sicherlich komplizieren und Leistungsprobleme verursachen könnten (Kosten für "ordnungsgemäße" Behandlung), sollten die Kosten für diese Merkmale im Schema nahe Null liegen.
Da die meisten offensichtlichen Zyklen in RDBs in hierarchischen Strukturen (Organigramm, Teil, Unterteil usw.) auftreten, ist es bedauerlich, dass SQL Server das Schlimmste annimmt. dh Schema-Zyklus == Datenzyklus. Wenn Sie RI-Einschränkungen verwenden, können Sie tatsächlich keinen Zyklus in den Daten erstellen!
Ich vermute, dass das Mehrwegproblem ähnlich ist; Das heißt, mehrere Pfade im Schema implizieren nicht unbedingt mehrere Pfade in den Daten, aber ich habe weniger Erfahrung mit dem Multipath-Problem.
Natürlich , wenn SQL Server hat Zyklen erlauben es noch unter dem Vorbehalt einer Tiefe von 32 sein würde, aber das ist wahrscheinlich ausreichend für die meisten Fälle. (Schade, dass dies jedoch keine Datenbankeinstellung ist!)
"Statt zu löschen" -Trigger funktionieren auch nicht. Beim zweiten Besuch einer Tabelle wird der Trigger ignoriert. Wenn Sie also wirklich eine Kaskade simulieren möchten, müssen Sie gespeicherte Prozeduren bei Vorhandensein von Zyklen verwenden. Der Trigger "Statt zu löschen" würde jedoch für Mehrwegfälle funktionieren.
Celko schlägt einen "besseren" Weg vor, um Hierarchien darzustellen, der keine Zyklen einführt, aber es gibt Kompromisse.
quelle
In einem Artikel wird erläutert, wie mehrere Löschpfade mithilfe von Triggern ausgeführt werden. Vielleicht ist dies für komplexe Szenarien nützlich.
http://www.mssqltips.com/sqlservertip/2733/solving-the-sql-server-multiple-cascade-path-issue-with-a-trigger/
quelle
Laut Sound haben Sie eine OnDelete / OnUpdate-Aktion auf einem Ihrer vorhandenen Fremdschlüssel, mit der Sie Ihre Codetabelle ändern können.
Wenn Sie also diesen Fremdschlüssel erstellen, entsteht ein zyklisches Problem.
ZB das Aktualisieren von Mitarbeitern, bewirkt, dass Codes durch eine On Update-Aktion geändert werden, dass Mitarbeiter durch eine On Update-Aktion geändert werden ... etc ...
Wenn Sie Ihre Tabellendefinitionen für beide Tabellen und Ihre Fremdschlüssel- / Einschränkungsdefinitionen veröffentlichen, sollten wir Ihnen mitteilen können, wo das Problem liegt ...
quelle
Dies liegt daran, dass der Mitarbeiter möglicherweise über eine Sammlung anderer Unternehmen verfügt, z. B. über Qualifikationen und über die Qualifikation über einige andere Sammlungsuniversitäten, z
}}
}}
}}
Auf DataContext könnte es wie folgt sein
}}
In diesem Fall gibt es eine Kette vom Mitarbeiter zur Qualifikation und von der Qualifikation zur Universität. Also warf es mir die gleiche Ausnahme zu.
Es hat bei mir funktioniert, als ich mich verändert habe
Zu
quelle
Trigger ist die Lösung für dieses Problem:
quelle
Dies ist ein Fehler vom Typ Datenbank-Triggerrichtlinien. Ein Trigger ist Code und kann einer Kaskadenbeziehung wie Kaskadenlöschung einige Intelligenzen oder Bedingungen hinzufügen. Möglicherweise müssen Sie die zugehörigen Tabellenoptionen darauf spezialisieren , z. B. Deaktivieren von CascadeOnDelete :
Oder Schalten Sie diese Funktion vollständig aus:
quelle
Meine Lösung für dieses Problem mit ASP.NET Core 2.0 und EF Core 2.0 bestand darin, Folgendes in der angegebenen Reihenfolge auszuführen:
Führen Sie den
update-database
Befehl in der Package Management Console (PMC) aus, um die Datenbank zu erstellen (dies führt zu dem Fehler "Einführung der FOREIGN KEY-Einschränkung ... kann Zyklen oder mehrere Kaskadenpfade verursachen").Führen Sie den
script-migration -Idempotent
Befehl in PMC aus, um ein Skript zu erstellen, das unabhängig von den vorhandenen Tabellen / Einschränkungen ausgeführt werden kannNehmen Sie das resultierende Skript und suchen
ON DELETE CASCADE
und ersetzen Sie es durchON DELETE NO ACTION
Führen Sie die geänderte SQL für die Datenbank aus
Jetzt sollten Ihre Migrationen auf dem neuesten Stand sein und die kaskadierenden Löschvorgänge sollten nicht stattfinden.
Schade, dass ich in Entity Framework Core 2.0 keine Möglichkeit gefunden habe, dies zu tun.
Viel Glück!
quelle