Entity Framework Core 导航属性错误

5

我想制作一个简单的应用程序来尝试 Entity Framework Core,但是我在设置实体之间的关系时遇到了问题。我的实体:

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; }
}

我尝试设置关系的配置类:

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;");
    }
}

当我试图添加迁移或向数据库添加内容时,我看到了这个错误:

System.InvalidOperationException:'无法将属性或导航“Spec”添加到实体类型“Doctor”中,因为在实体类型“Doctor”上已经存在具有相同名称的属性或导航。'

我真的不知道如何修复它,我尝试使用注释代替Fluent API,但结果相同。


更新:即使没有尝试使用Fluent API设置外键,我在Database.EnsureCreated();上遇到了另一个错误。 “System.InvalidOperationException:'属性'Doctor.Spec'的类型为'Spec',当前数据库提供程序不支持。要么更改属性CLR类型,要么使用'[NotMapped]'属性或在'OnModelCreating'中使用'EntityTypeBuilder.Ignore'忽略该属性。” - Dan
1个回答

6
异常的原因是以下代码行:
ModelBuilder.Entity<Doctor>().Property(d => d.Spec).IsRequired();

因为Doctor.Spec是一个导航属性。
public class Doctor
{
    // ...
    public Spec Spec { get; set; }
}

并且导航属性不能通过Property流畅API进行配置。

因此,只需删除该行。引用导航属性是必需还是可选是通过关系配置进行控制的。在这种情况下

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

尽管 IsRequired 是从 FK 属性类型自动派生的 - 因为 SpecID 是非空的,所以该关系是必需的。
有关更多信息,请参见 必需和可选属性 必需和可选关系文档主题。

谢谢,你的解决方案有效! 所以,除了导航属性的错误之外,其他都没问题了? - Dan
1
还没有仔细检查。但如果您有其他问题,可以随时问 :) 我个人会跳过所有常规的流畅配置 - 例如所有 HasKey,所有 IsRequired 用于 intTimeSpan(即非空类型)等。 - Ivan Stoev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接