Ich habe eine Weile damit gerungen und kann nicht genau herausfinden, was passiert. Ich habe eine Kartenentität, die Seiten enthält (normalerweise 2) - und sowohl Karten als auch Seiten haben eine Stufe. Ich verwende EF Codefirst-Migrationen und die Migrationen schlagen mit diesem Fehler fehl:
Die Einführung der FOREIGN KEY-Einschränkung 'FK_dbo.Sides_dbo.Cards_CardId' in der Tabelle 'Sides' 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.
Hier ist meine Karte Einheit:
public class Card
{
public Card()
{
Sides = new Collection<Side>();
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int CardId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
[ForeignKey("CardId")]
public virtual ICollection<Side> Sides { get; set; }
}
Hier ist meine Side Einheit:
public class Side
{
public Side()
{
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int SideId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
public int CardId { get; set; }
[ForeignKey("CardId")]
public virtual Card Card { get; set; }
}
Und hier ist meine Bühnenentität :
public class Stage
{
// Zero
public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE");
// Ten seconds
public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO");
public static IEnumerable<Stage> Values
{
get
{
yield return ONE;
yield return TWO;
}
}
public int StageId { get; set; }
private readonly TimeSpan span;
public string Title { get; set; }
Stage(TimeSpan span, string title)
{
this.span = span;
this.Title = title;
}
public TimeSpan Span { get { return span; } }
}
Was seltsam ist, ist, wenn ich meiner Stage-Klasse Folgendes hinzufüge:
public int? SideId { get; set; }
[ForeignKey("SideId")]
public virtual Side Side { get; set; }
Die Migration wird erfolgreich ausgeführt. Wenn ich SSMS öffne und mir die Tabellen ansehe, kann ich sehen, dass Stage_StageId
das hinzugefügt wurde Cards
(wie erwartet / gewünscht), Sides
enthält jedoch keinen Verweis aufStage
(nicht erwartet) enthält.
Wenn ich dann hinzufüge
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
In meiner Nebenklasse wird eine StageId
Spalte zu meiner hinzugefügtSide
Tabelle .
Dies funktioniert, aber jetzt in meiner gesamten Anwendung Stage
enthält jeder Verweis auf a SideId
, was in einigen Fällen völlig irrelevant ist. Ich möchte meinen Card
und Side
Entitäten einfach eine Stage
Eigenschaft geben, die auf der obigen Stage-Klasse basiert, ohne die Stage-Klasse nach Möglichkeit mit Referenzeigenschaften zu verschmutzen ... was mache ich falsch?
Side
zulassen. Fügen Sie also in Class eine Nullable-Ganzzahl hinzu und entfernen Sie das[Required]
Attribut =>public int? CardId { get; set; }
DeleteBehavior.Restrict
oder deaktivierenDeleteBehavior.SetNull
.Antworten:
Da
Stage
ist erforderlich , alle Eins-zu-viele Beziehungen , in denenStage
beteiligt ist wird standardmäßig Cascading löschen aktiviert. Dies bedeutet, wenn Sie eineStage
Entität löschenSide
Card
und kaskadiertCard
undSide
hat eine erforderliche Eins-zu-Viele-Beziehung zum kaskadierenden Löschen, das standardmäßig wieder aktiviert ist. Es wird dann vonCard
zu kaskadierenSide
Sie haben also zwei kaskadierende Löschpfade von
Stage
bisSide
- was die Ausnahme verursacht.Sie müssen entweder die
Stage
Option in mindestens einer der Entitäten aktivieren (dh das[Required]
Attribut aus denStage
Eigenschaften entfernen ) oder das kaskadierende Löschen mit der Fluent-API deaktivieren (mit Datenanmerkungen nicht möglich):quelle
Stage
. Andere Beziehungen bleiben unverändert.Stage
LöschungSide
direkt und durch aCard
Ich hatte einen Tisch, der eine zirkuläre Beziehung zu anderen hatte, und ich bekam den gleichen Fehler. Es stellte sich heraus, dass es sich um den Fremdschlüssel handelt, der nicht nullwertfähig war. Wenn der Schlüssel nicht nullbar ist, muss das zugehörige Objekt gelöscht werden, und Kreisbeziehungen lassen dies nicht zu. Verwenden Sie also einen nullbaren Fremdschlüssel.
quelle
int?
anstattint
es nullbar zu machen.Jeder, der sich fragt, wie es im EF-Kern geht:
quelle
builder.HasOne(x => x.Stage).WithMany().HasForeignKey(x => x.StageId).OnDelete(DeleteBehavior.Restrict);
builder _ .Entity<TEntity>() _
vorHasOne()
kann ... genannt werdenIEntityTypeConfiguration<T>
. Ich kann mich nicht erinnern, diesebuilder.Entity<T>
Methode damals gesehen zu haben, aber ich könnte mich irren. Trotzdem werden beide funktionieren :)Ich habe diesen Fehler für viele Entitäten erhalten, als ich von einem EF7-Modell auf eine EF6-Version migriert habe. Ich wollte nicht jede Entität einzeln durchgehen müssen, also benutzte ich:
quelle
Sie können cascadeDelete auf false oder true setzen (in Ihrer Migrationsmethode Up ()). Hängt von Ihrer Anforderung ab.
quelle
UP
Methode möglicherweise durch externe Operationen geändert wird.In .NET Core habe ich die Option onDelete in ReferencialAction.NoAction geändert
quelle
Ich hatte dieses Problem auch, ich habe es sofort mit dieser Antwort aus einem ähnlichen Thread gelöst
In meinem Fall wollte ich den abhängigen Datensatz beim Löschen des Schlüssels nicht löschen. Wenn dies in Ihrer Situation der Fall ist, ändern Sie einfach den Booleschen Wert in der Migration in false:
Wenn Sie Beziehungen erstellen, die diesen Compilerfehler auslösen, aber die Kaskadenlöschung beibehalten möchten, ist dies wahrscheinlich. Sie haben ein Problem mit Ihren Beziehungen.
quelle
Ich habe das behoben. Wenn Sie die Migration hinzufügen, wird in der Up () -Methode eine Zeile wie die folgende angezeigt:
Wenn Sie nur cascadeDelete am Ende löschen, funktioniert es.
quelle
Nur zu Dokumentationszwecken kann dieses Problem für jemanden, der in die Zukunft kommt, so einfach gelöst werden. Mit dieser Methode können Sie eine Methode ausführen, die einmal deaktiviert wurde, und Sie können normal auf Ihre Methode zugreifen
Fügen Sie diese Methode der Kontextdatenbankklasse hinzu:
quelle
Das klingt komisch und ich weiß nicht warum, aber in meinem Fall geschah das, weil mein ConnectionString "." im Attribut "Datenquelle". Nachdem ich es in "localhost" geändert hatte, funktionierte es wie ein Zauber. Es war keine weitere Änderung erforderlich.
quelle
In .NET Core habe ich mit allen oberen Antworten gespielt - aber ohne Erfolg. Ich habe viele Änderungen an der DB-Struktur vorgenommen und jedes Mal neue Migrationsversuche hinzugefügt
update-database
, aber den gleichen Fehler erhalten.Dann fing ich
remove-migration
eins nach dem anderen an, bis die Package Manager-Konsole mir eine Ausnahme warf:Danach habe ich neue Migration (
add-migration
) hinzugefügt undupdate-database
erfolgreichMein Vorschlag wäre also: Löschen Sie alle Ihre temporären Migrationen bis zu Ihrem aktuellen DB-Status.
quelle
Die vorhandenen Antworten sind großartig. Ich wollte nur hinzufügen, dass ich aus einem anderen Grund auf diesen Fehler gestoßen bin. Ich wollte eine anfängliche EF-Migration für eine vorhandene Datenbank erstellen, habe jedoch die -IgnoreChanges nicht verwendet Datenbank Flag und den Befehl Update-Database auf eine leere Datenbank angewendet (auch bei vorhandenen Fehlern).
Stattdessen musste ich diesen Befehl ausführen, wenn die aktuelle Datenbankstruktur die aktuelle ist:
Es gibt wahrscheinlich ein echtes Problem in der Datenbankstruktur, aber rette die Welt Schritt für Schritt ...
quelle
Der einfache Weg ist, Bearbeiten Sie Ihre Migrationsdatei
(cascadeDelete: true)
in(cascadeDelete: false)
dann nach dem Update-Befehl Datenbank in Ihrem Package Manager Console.if es das Problem mit der letzten Migration zugewiesen werden dann alles in Ordnung. Überprüfen Sie andernfalls Ihren früheren Migrationsverlauf, kopieren Sie diese Dinge, fügen Sie sie in Ihre letzte Migrationsdatei ein, und machen Sie danach dasselbe. es funktioniert perfekt für mich.quelle
Wenn Ihre Migration fehlschlägt, stehen Ihnen mehrere Optionen zur Verfügung: 'Einführung der FOREIGN KEY-Einschränkung' FK_dbo.RecommendedBook_dbo.Department_DepartmentID 'in Tabelle' RecommendedBook 'kann Zyklen oder mehrere Kaskadenpfade verursachen. Geben Sie ON DELETE NO ACTION oder ON UPDATE NO ACTION an oder ändern Sie andere FOREIGN KEY-Einschränkungen. Einschränkung oder Index konnten nicht erstellt werden. Siehe vorherige Fehler. '
Hier ist ein Beispiel für die Verwendung der Einschränkungen "Andere FOREIGN KEY-Änderungen ändern", indem "cascadeDelete" in der Migrationsdatei auf "false" gesetzt und anschließend "update-database" ausgeführt wird.
quelle
Keine der oben genannten Lösungen hat bei mir funktioniert. Was ich tun musste, war, ein nullfähiges int (int?) Für den Fremdschlüssel zu verwenden, das nicht erforderlich war (oder keinen nicht null-Spaltenschlüssel), und dann einige meiner Migrationen zu löschen.
Löschen Sie zunächst die Migrationen und versuchen Sie dann das nullable int.
Problem war sowohl eine Modifikation als auch ein Modelldesign. Es war keine Codeänderung erforderlich.
quelle
Machen Sie Ihre Fremdschlüsselattribute nullbar. Das wird funktionieren.
quelle