EF Core Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths RRS feed

  • Question

  • Hey guys,

    I'm trying to create my Code First EF Core model. I thought I understood the cascade mechanic but somehow the following fluent configuration throws the exception from the title. I was playing around but most of the problems are with the entity DEFECT. I just can't see where I'm wrong.

    fluent api:

     builder.Entity<ApplicationUser>().HasMany(u => u.Claims).WithOne().HasForeignKey(c => c.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
                builder.Entity<ApplicationUser>().HasMany(u => u.Roles).WithOne().HasForeignKey(r => r.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
                builder.Entity<ApplicationRole>().HasMany(r => r.Claims).WithOne().HasForeignKey(c => c.RoleId).IsRequired().OnDelete(DeleteBehavior.Cascade);
                builder.Entity<ApplicationRole>().HasMany(r => r.Users).WithOne().HasForeignKey(r => r.RoleId).IsRequired().OnDelete(DeleteBehavior.Cascade);
                builder.Entity<Customer>().HasIndex(c => c.Name);
                builder.Entity<Customer>().HasOne(a => a.ConnectedCustomer).WithOne().HasForeignKey<Customer>(fk => fk.ConnectedCustomerId);
                builder.Entity<Policy>().HasIndex(p => p.Number);
                builder.Entity<Policy>().HasOne(a => a.Customer).WithMany(b => b.Policies).HasForeignKey(fk => fk.CustomerId).OnDelete(DeleteBehavior.Cascade);
                builder.Entity<Policy>().HasOne(a => a.Category).WithMany(b => b.Policies).HasForeignKey(fk => fk.CategoryId).OnDelete(DeleteBehavior.SetNull);
                builder.Entity<Policy>().HasOne(a => a.ManagedBy).WithMany(b => b.ManagedPolicies).HasForeignKey(fk => fk.ManagedById).OnDelete(DeleteBehavior.SetNull);
                builder.Entity<Policy>().HasOne(a => a.PolicyBefore).WithOne().HasForeignKey<Policy>(f => f.PolicyBeforeId);
                builder.Entity<Policy>().HasOne(a => a.PolicyNext).WithOne().HasForeignKey<Policy>(f => f.PolicyNextId);
                builder.Entity<Defect>().HasIndex(d => d.Number);
                builder.Entity<Defect>().HasOne(a => a.Policy).WithMany(b => b.Defects).HasForeignKey(fk => fk.PolicyId).OnDelete(DeleteBehavior.Cascade);
                builder.Entity<Defect>().HasOne(a => a.ClosedByUser).WithMany(b => b.ClosedDefects).HasForeignKey(fk => fk.ClosedByUserId).OnDelete(DeleteBehavior.SetNull);
                builder.Entity<Defect>().HasOne(a => a.ResponsibleUser).WithMany(b => b.ResponsibleForDefects).HasForeignKey(fk => fk.ResponsibleUserId).OnDelete(DeleteBehavior.SetNull);
                builder.Entity<PolicyCategory>().Property(p => p.Name).IsRequired();
                builder.Entity<UserTask>().HasOne(a => a.Customer).WithMany(b => b.Tasks).HasForeignKey(fk => fk.CustomerId).OnDelete(DeleteBehavior.SetNull);
                builder.Entity<UserTask>().HasOne(a => a.Policy).WithMany(b => b.Tasks).HasForeignKey(fk => fk.PoliyId).OnDelete(DeleteBehavior.SetNull);
                builder.Entity<UserTask>().HasOne(a => a.Defect).WithMany(b => b.Tasks).HasForeignKey(fk => fk.DefectId).OnDelete(DeleteBehavior.SetNull);
                builder.Entity<UserTask>().HasOne(a => a.User).WithMany(b => b.Tasks).HasForeignKey(fk => fk.UserId).OnDelete(DeleteBehavior.SetNull);
                builder.Entity<ApplicationFile>().HasOne(o => o.Customer).WithMany(f => f.Files).OnDelete(DeleteBehavior.Cascade);
                builder.Entity<ApplicationFile>().HasOne(o => o.Defect).WithMany(f => f.Files).OnDelete(DeleteBehavior.Cascade);
                builder.Entity<ApplicationFile>().HasOne(o => o.Policy).WithMany(f => f.Files).OnDelete(DeleteBehavior.Cascade);
                builder.Entity<ApplicationFile>().HasOne(o => o.Task).WithMany(f => f.Files).OnDelete(DeleteBehavior.Cascade);
                builder.Entity<ApplicationFile>().HasOne(o => o.Categories).WithMany(f => f.Files).OnDelete(DeleteBehavior.Cascade);

    All the entities have the same structure, so a virtual collection property on one end and a navigation property on the other:


    public int Id { get; set; }
            public string Number { get; set; }
            public string Name { get; set; }
            public string Info { get; set; }
            public DateTime DefectDate { get; set; }
            public DateTime ReportDate { get; set; }
            public DateTime? ClosingDate { get; set; }
            public virtual ApplicationUser ResponsibleUser { get; set; }
            public string ResponsibleUserId { get; set; }
            public virtual ApplicationUser ClosedByUser { get; set; }
            public string ClosedByUserId { get; set; }
            public virtual Policy Policy { get; set; }
            public int PolicyId { get; set; }
            public virtual ICollection<ApplicationFile> Files { get; set; }
            public virtual ICollection<UserTask> Tasks { get; set; }

    Application User:

     public virtual ICollection<Defect> ResponsibleForDefects { get; set; }
            public virtual ICollection<Defect> ClosedDefects { get; set; }

    And the error: 

    Introducing FOREIGN KEY constraint 'FK_Defects_AspNetUsers_ResponsibleUserId' on table 'Defects' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
    Could not create constraint or index. See previous errors.

    Any idea where I'm wrong?


    Wednesday, February 14, 2018 12:44 AM


All replies

  • Hi MegalomaniaX,

    Please refer to the following thread, which said that this is restriction of MS SQL Server itself. Table with several FKs may have only one of them with cascade delete.


    Best regards,


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by MegalomaniaX Wednesday, February 14, 2018 11:41 AM
    Wednesday, February 14, 2018 7:45 AM
  • Hey Zhanglong,

    thanks for pointing that out! Removed the multiple cascades and will perfomr the clean up manually.

    Wednesday, February 14, 2018 11:41 AM