Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core - may cause cycles or multiple cascade paths

I've set up what I thought was a pretty simple database.. However I am getting the following error.

Introducing FOREIGN KEY constraint 'FK_User_Suburb_SuburbId' on table 'User' 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.

Here is my CATALOGCOntext:

using JobsLedger.CATALOG.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

namespace JobsLedger.CATALOG
{
    public class CATALOGContext : DbContext
    {
        public DbSet<Tenant> Tenants { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<Role> Roles { get; set; }
        public DbSet<State> States { get; set; }
        public DbSet<Suburb> Suburbs { get; set; }
        public DbSet<CATALOGCounter> Counters { get; set; }


        public CATALOGContext(DbContextOptions options) : base(options) { }



        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            foreach (var entity in modelBuilder.Model.GetEntityTypes())
            {
                entity.Relational().TableName = entity.DisplayName();
            }

            // User
            modelBuilder.Entity<User>().Property(u => u.UserName).IsRequired().HasMaxLength(50);
            modelBuilder.Entity<User>().Property(u => u.UserFirstName).IsRequired().HasMaxLength(100);
            modelBuilder.Entity<User>().Property(u => u.UserLastName).IsRequired().HasMaxLength(100);
            modelBuilder.Entity<User>().Property(u => u.Email).IsRequired().HasMaxLength(200);
            modelBuilder.Entity<User>().Property(u => u.HashedPassword).IsRequired().HasMaxLength(200);
            modelBuilder.Entity<User>().Property(u => u.Salt).IsRequired().HasMaxLength(200);

            modelBuilder.Entity<User>()
                .HasOne<Suburb>(s => s.Suburb)
                .WithMany(u => u.Users)
                .HasForeignKey(u => u.SuburbId)
                .IsRequired(false);

            // Role
            modelBuilder.Entity<Role>().Property(r => r.Name).IsRequired().HasMaxLength(50);

            modelBuilder.Entity<Role>()
                .HasOne<User>(u => u.User)
                .WithOne(r => r.Role)
                .HasForeignKey<User>(u => u.RoleId);

            // TenantAccount
            modelBuilder.Entity<Tenant>().Property(t => t.TenantNo).HasMaxLength(20);
            modelBuilder.Entity<Tenant>().Property(t => t.Company).HasMaxLength(100).IsRequired();
            modelBuilder.Entity<Tenant>().Property(t => t.ContactLastName).HasDefaultValue(false).IsRequired();
            modelBuilder.Entity<Tenant>().Property(t => t.Email).HasMaxLength(500).IsRequired();
            modelBuilder.Entity<Tenant>().Property(t => t.MobilePhone).HasMaxLength(20).IsRequired();
            modelBuilder.Entity<Tenant>().Property(t => t.OfficePhone).HasMaxLength(20);
            modelBuilder.Entity<Tenant>().Property(t => t.CompanyEmail).HasMaxLength(500);
            modelBuilder.Entity<Tenant>().Property(t => t.Address1).HasMaxLength(500);
            modelBuilder.Entity<Tenant>().Property(t => t.Address2).HasMaxLength(500);
            modelBuilder.Entity<Tenant>().Property(t => t.ABN).HasMaxLength(14);
            modelBuilder.Entity<Tenant>().Property(t => t.Database).HasMaxLength(100).IsRequired();
            modelBuilder.Entity<Tenant>().Property(t => t.IsLocked).HasDefaultValue(false);

            modelBuilder.Entity<Tenant>()
                .HasOne<User>(s => s.User)
                .WithMany(ta => ta.Tenants)
                .HasForeignKey(u => u.UserId);

            modelBuilder.Entity<Tenant>()
                .HasOne(s => s.Suburb)
                .WithMany(ta => ta.Tenants)
                .HasForeignKey(ta => ta.SuburbId);

            // State
            modelBuilder.Entity<State>().Property(s => s.StateShortName).HasMaxLength(3).IsRequired();
            modelBuilder.Entity<State>().Property(s => s.StateName).HasMaxLength(30).IsRequired();

            // Suburb
            modelBuilder.Entity<Suburb>().Property(s => s.SuburbName).HasMaxLength(3).IsRequired();
            modelBuilder.Entity<Suburb>().Property(s => s.PostCode).HasMaxLength(30).IsRequired();

            modelBuilder.Entity<Suburb>()
                .HasOne<State>(s => s.State)
                .WithMany(su => su.Suburbs)
                .HasForeignKey(st => st.StateId);
        }
    }
}

Here is my user:

...
        public int? SuburbId { get; set; }
        public Suburb Suburb { get; set; }

        public int RoleId { get; set; }
        public Role Role { get; set; }

        public virtual ICollection<Tenant> Tenants { get; set; }

Here is my Suburb which was also mentioned..

Wondering if someone might highlight why the migrations work but when I try and spin up a database it it errors with above error..

Simon

like image 529
si2030 Avatar asked May 03 '19 13:05

si2030


People also ask

What is the difference between EF6 and EF core?

Keep using EF6 if the data access code is stable and not likely to evolve or need new features. Port to EF Core if the data access code is evolving or if the app needs new features only available in EF Core. Porting to EF Core is also often done for performance.

Is EF core faster than EF6?

EF Core 6.0 itself is 31% faster executing queries. Heap allocations have been reduced by 43%.

Is EF core an ORM?

Entity Framework Core is what's known as an Object Relational Mapper (ORM). Created by Microsoft, the library allows developers to work abstractly with their database.


2 Answers

For others that finds this question, this is enough:

modelBuilder.Entity<User>()
     .HasOne(u => u.Suburb)
     .WithMany(s => s.Users)
     .OnDelete(DeleteBehavior.Restrict);

If you don't have want a list property in Suburb with Users you can do it like this as well:

modelBuilder.Entity<User>()
     .HasOne(u => u.Suburb)
     .WithMany()
     .OnDelete(DeleteBehavior.Restrict);
like image 172
Ogglas Avatar answered Sep 29 '22 16:09

Ogglas


Your User entity ForeignFey Fluent API configuration should be as follows:

modelBuilder.Entity<User>()
     .HasOne<Suburb>(s => s.Suburb)
     .WithMany(u => u.Users)
     .HasForeignKey(u => u.SuburbId)
     .IsRequired(false);
     .OnDelete(DeleteBehavior.Restrict); // <-- Here it is
like image 26
TanvirArjel Avatar answered Sep 29 '22 17:09

TanvirArjel