Entity Framework: Wie triggers man “FOREIGN KEY constraint kann Zyklen oder mehrere Kaskadenpfade verursachen”?

Es gibt viele Fragen zu diesem Problem, aber ich konnte meinen Fall nicht lösen. Kann jemand bitte einen Blick darauf casting:

Ich habe einen Office , der eine Ein-Mann-Beziehung mit den Tabellen von Doctor und Secretary . Die beiden letzten Tabellen sind von der Employee Tabelle abgeleitet, die eine shared-primary-key-Beziehung mit der vordefinierten sqlmembershipprovider Tabelle aufweist, die von sqlmembershipprovider erstellt wurde. Es scheint, dass es eine viele-viele Beziehung zwischen der Users Tabelle und der Roles Tabelle gibt, in der ich keine Hand habe.

Mein Problem bestand darin, eine (null, eins) – (eine) Beziehung zwischen meiner Employee Tabelle und jener Users Tabelle zu erstellen, die ich mit einer gemeinsamen Primärschlüssel-Beziehung zwischen ihnen beendet habe und dann den Fehler ausgetriggers habe. (Gibt es eine bessere Lösung für dieses Problem?)

Hier ist der Fehler:

Das Einführen der FOREIGN KEY-Einschränkung ‘FK_dbo.aspnet_UsersInRoles_dbo.aspnet_Users_UserId’ für die Tabelle ‘aspnet_UsersInRoles’ 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. Constraint konnte nicht erstellt werden. Siehe vorherige Fehler.

Hier sind meine Codes und Mitgliedscodes nach dem Reverse Engineering:

 public class Office { public Office() { this.Doctors = new HashSet(); this.Secretaries = new HashSet(); } [Key] public System.Guid OfficeId { get; set; } public virtual ICollection Doctors { get; set; } public virtual ICollection Secretaries { get; set; } } public class Employee { [Key, ForeignKey("User")] [DatabaseGenerated(DatabaseGeneratedOption.None)] public System.Guid Id { get; set; } public string Name { get; set; } [ForeignKey("Office")] public System.Guid OfficeId { get; set; } // shared primary key public virtual aspnet_Users User { get; set; } public virtual Office Office { get; set; } } public class Doctor :Employee { public Doctor() { this.Expertises = new HashSet(); } //the rest.. public virtual ICollection Expertises { get; set; } } public class Secretary : Employee { // blah blah } public class aspnet_Users { public aspnet_Users() { this.aspnet_Roles = new List(); } public System.Guid ApplicationId { get; set; } public System.Guid UserId { get; set; } //the rest.. public virtual aspnet_Applications aspnet_Applications { get; set; } public virtual ICollection aspnet_Roles { get; set; } } public class aspnet_Roles { public aspnet_Roles() { this.aspnet_Users = new List(); } public System.Guid ApplicationId { get; set; } public System.Guid RoleId { get; set; } //the rest.. public virtual aspnet_Applications aspnet_Applications { get; set; } public virtual ICollection aspnet_Users { get; set; } } 

EDIT: und die Beziehungen gehen tiefer, es gibt eine viel-eins-Beziehung zwischen Users Tabelle und Applications Tabelle, auch zwischen Roles und Applications zu.

    Sie können die flüssige API verwenden, um die Aktionen anzugeben, die die Fehlermeldung vorschlägt.

    In deinem Kontext:

     protected override void OnModelCreating( DbModelBuilder modelBuilder ) { base.OnModelCreating(modelBuilder); modelBuilder.Entity().HasMany(i => i.Users).WithRequired().WillCascadeOnDelete(false); } 

    Beachten Sie, dass Sie die Definition für die Tabelle aspnet_UsersInRoles nicht einbezogen haben, damit dieser Code möglicherweise nicht funktioniert.

    Eine andere Möglichkeit besteht darin, alle CASCADE DELETES zu entfernen, indem Sie diese hinzufügen

     modelBuilder.Conventions.Remove(); 

    Wenn Sie weitere Informationen zum Konfigurieren von Beziehungen mit der fließenden API benötigen, empfehle ich http://msdn.microsoft.com/en-US/data/jj591620

    Sie können auch Ihre Migrationsklasse ändern. In meinem Fall in der Migrationsklasse war:

     CreateTable( "dbo.Spendings", c => new { SpendingId = c.Int(nullable: false, identity: true), CategoryGroupId = c.Int(nullable: false), CategoryId = c.Int(nullable: false), Sum = c.Single(nullable: false), Date = c.DateTime(nullable: false), Comment = c.String(), UserId = c.String(), LastUpdate = c.String(), }) .PrimaryKey(t => t.SpendingId) .ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: true) .ForeignKey("dbo.CategoryGroups", t => t.CategoryGroupId, cascadeDelete: true) .Index(t => t.CategoryGroupId) .Index(t => t.CategoryId); 

    Nach dem Entfernen von “cascadeDelete: true” funktioniert die Update-database einwandfrei.

    ODER als false

      .ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: false) 
      protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove(); } 

    Fügen Sie diesen Code im Kontext hinzu

    Aufgrund Ihrer Kommentare besteht das Problem darin, dass Sie dieselbe PK in beiden Tabellen verwenden. Ich würde das sofort ändern, Benutzer PK als ein zusätzliches Feld in Mitarbeitern mit einer FK-Beziehung zu Benutzern (eins zu eins, denke ich). Und fügen Sie den Benutzern eine unabhängige PK hinzu (eine weitere Anleitung, um den Rest Ihrer Tabellen zu respektieren). Wenn Sie sicherstellen möchten, dass der neue Fremdschlüssel in Employees (der Benutzer, der auf Benutzer verweist) eindeutig ist, können Sie immer einen eindeutigen Index hinzufügen.

    Auf diese Weise behalten Sie Ihre Struktur und Sie werden den Zyklus los.

    Nur ein Update :

    Wie andere Antworten vorschlagen, müssen Sie beim Löschen keine Aktion ausführen. Aktualisierte Vorgehensweise für Entityframework Core 1.0 ist wie folgt

     table.ForeignKey(name: "FK_Cities_Regions_RegionId", column: x => x.RegionId, principalTable: "Regions", principalColumn: "RegionId", onDelete: ReferentialAction.NoAction); 

    HINWEIS: onDelete Sie ReferentialAction.NoAction on onDelete