Entity Framework Core Navigation Properties Error

10,871

The cause of the exception is the following line:

ModelBuilder.Entity<Doctor>().Property(d => d.Spec).IsRequired();

because Doctor.Spec is a navigation property

public class Doctor
{
    // ...
    public Spec Spec { get; set; }
}

and navigation properties cannot be configured via Property fluent API.

So simply remove that line. Whether reference navigation property is required or optional is controlled via relationship configuration. In this case

ModelBuilder.Entity<Doctor>()
   .HasOne(d => d.Spec)
   .WithMany(s => s.Doctors)
   .HasForeignKey(d => d.SpecID)
   .IsRequired(); // <--

although the IsRequired is automatically derived from the FK property type - since SpecID is non nullable, then the relationship is required.

For more info, see Required and Optional Properties and Required and Optional Relationships documentation topics.

Share:
10,871

Related videos on Youtube

Dan
Author by

Dan

Updated on June 04, 2022

Comments

  • Dan
    Dan almost 2 years

    I'm trying to make a simple app to try Entity Framework Core, but i a have problem with setting up relations between entities. My entities:

    public class Card
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public string Adress { get; set; }
        public DateTime DoB { get; set; }
        public DateTime DoS { get; set; }
        public User Portal { get; set; }
        public List<Reservation> Res { get; set; }
    }
    public class Doctor
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public string Email { get; set; }
        public TimeSpan Start_Working { get; set; }
        public TimeSpan End_Working { get; set; }
        public List<Reservation> Reservations { get; set; }
        public int SpecID { get; set; }
        public Spec Spec { get; set; }
    }
    public class Reservation
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public DateTime DoR { get; set; }
        public string Info { get; set; }
        public int CardID { get; set; }
        public Card Card_Nav_R { get; set; }
        public int DoctorID { get; set; }
        public Doctor Doctor { get; set; }
    }
    public class Spec
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Name { get; set; }
        public List<Doctor> Doctors { get; set; }
    }
    public class User
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
        public int CardID { get; set; }
        public Card Card { get; set; }
    }
    

    And a configuration class where i tried to set up relations:

    class ApplicationContext:DbContext
    {
        public DbSet<User> Users { get; set; }
        public DbSet<Card> Cards { get; set; }
        public DbSet<Reservation> Reservations { get; set; }
        public DbSet<Doctor> Doctors { get; set; }
        public DbSet<Spec> Specs { get; set; }
    
        public ApplicationContext()
        {
            Database.EnsureCreated();
        }
        protected override void OnModelCreating(ModelBuilder ModelBuilder)
        {
              ModelBuilder.Entity<User>().HasKey(u => u.Id);
              ModelBuilder.Entity<Card>().HasKey(c => c.Id);
              ModelBuilder.Entity<Doctor>().HasKey(d => d.Id);
              ModelBuilder.Entity<Spec>().HasKey(s => s.Id);
              ModelBuilder.Entity<Reservation>().HasKey(r => r.Id);
    
              ModelBuilder.Entity<User>().Property(u => u.Email).IsRequired();
              ModelBuilder.Entity<User>().Property(u => u.Password).IsRequired();
    
              ModelBuilder.Entity<Card>().Property(c => c.Name).IsRequired();
              ModelBuilder.Entity<Card>().Property(c => c.Surname).IsRequired();
              ModelBuilder.Entity<Card>().Property(c => c.DoB).IsRequired();
              ModelBuilder.Entity<Card>().Property(c => c.Adress).IsRequired();
    
              ModelBuilder.Entity<Doctor>().Property(d => d.Name).IsRequired();
              ModelBuilder.Entity<Doctor>().Property(d => d.Surname).IsRequired();
              ModelBuilder.Entity<Doctor>().Property(d => d.Spec).IsRequired();
              ModelBuilder.Entity<Doctor>().Property(d => d.Email).IsRequired();
              ModelBuilder.Entity<Doctor>().Property(d => d.Start_Working).IsRequired();
              ModelBuilder.Entity<Doctor>().Property(d => d.End_Working).IsRequired();
    
              ModelBuilder.Entity<Reservation>().Property(r => r.Info).IsRequired();
              ModelBuilder.Entity<Reservation>().Property(r => r.Card_Nav_R).IsRequired();
              ModelBuilder.Entity<Reservation>().Property(r => r.Doctor).IsRequired();
              ModelBuilder.Entity<Reservation>().Property(r => r.DoR).IsRequired();
    
            ModelBuilder.Entity<Spec>().Property(s => s.Name).IsRequired();
    
              ModelBuilder.Entity<Doctor>().HasOne<Spec>(d=>d.Spec).WithMany(s => s.Doctors).HasForeignKey(d => d.SpecID);
              ModelBuilder.Entity<User>().HasOne<Card>(u => u.Card).WithOne(c => c.Portal).HasForeignKey<User>(u => u.CardID);
              ModelBuilder.Entity<Reservation>().HasOne<Card>(r => r.Card_Nav_R).WithMany(c => c.Res).HasForeignKey(r => r.CardID);
              ModelBuilder.Entity<Reservation>().HasOne<Doctor>(r => r.Doctor).WithMany(d => d.Reservations).HasForeignKey(r => r.DoctorID); 
    
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=Simple_Try;Trusted_Connection=True;");
        }
    }
    

    So, when i tried to add migration or add something to database i saw this error:

    System.InvalidOperationException: 'The property or navigation 'Spec' cannot be added to the entity type 'Doctor' because a property or navigation with the same name already exists on entity type 'Doctor'.'

    I really don't know how to fix this, i tried to use annotations instead of Fluent API, but had the same result.

    • Dan
      Dan over 5 years
      UPDATE: Even without trying to set up foreign keys with Fluent API i have another error on Database.EnsureCreated(); 'System.InvalidOperationException: 'The property 'Doctor.Spec' is of type 'Spec' which is not supported by current database provider. Either change the property CLR type or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.''
  • Dan
    Dan over 5 years
    Thank you, your solution works! So, except this mistake with navigation property everything else seems allright?
  • Ivan Stoev
    Ivan Stoev over 5 years
    Haven't checked it carefully. But if you have other issues, you can always ask :) I would personally skip all the fluent configuration which is conventional - for instance all HasKey, all IsRequired for int, TimeSpan (i.e. non nullbale types) etc.