实体框架中的一对多和自引用

本文关键字:自引用 一对多 框架 实体 | 更新日期: 2023-09-27 18:35:30

我有两个具有以下关系的实体Ship(这些实体仅用于示例目的)

public class Entity
{
    public long ID { get; set; }
}
public class Doctor : Entity
{
    public string Name {get; set;}
    public string sprcialization { get; set;}
    public string Icollection<JrDoctor> childDoctors { get; set;}
}
public class JrDoctor : Entity
{
    public long? DoctorId { get; set;}
    public virtual Doctor Doctor { get; set;}
    public long? JuniorDoctorId { get; set;}
    [ForeignKey("JuniorDoctorId")]
    public virtual Doctor JuniorDoctor { get; set;}
}

实体框架中的这种关系正在 JrDoctor 表中创建一个额外的列Doctor_Id。为什么会这样?以及如何使用数据注释来避免它。

实体框架中的一对多和自引用

以下是 EF 的工作方式 - 如果它看到导航属性(在你的情况下Doctor),则 EF 了解这两个实体彼此相关。数据库中的关系由外键定义。所以 EF 生成名为 PropertyName_KeyColumnOfRelatedEntity 的外键。这就是为什么您在 JrDoctor 表中看到第 Doctor_Id 列的原因。

如果不希望默认生成的外键列,则应告诉 EF 它应该改用什么。这是通过数据注释属性或流畅配置完成的。我更喜欢后者:

modelBuilder.Entity<JrDoctor>()
    .HasOptional(jd => jd.Doctor) 
    .WithMany(d => d.childDoctors) 
    .HasForeignKey(jd => jd.DoctorId); // here you tell which column is FK

数据批注需要修改实体类。在您的情况下,您应该添加属性,该属性告诉导航属性的 FK 名称,就像您对 JuniorDoctor 所做的那样:

public class JrDoctor : Entity
{
    public long? DoctorId { get; set;}
    [ForeignKey("DoctorId")]
    public virtual Doctor Doctor { get; set;}
    public long? JuniorDoctorId { get; set;}
    [ForeignKey("JuniorDoctorId")]
    public virtual Doctor JuniorDoctor { get; set;}
}

InverseProperty做到了。

public class Entity
{
    public long ID { get; set; }
}
public class Doctor : Entity
{
    public string Name {get; set;}
    public string sprcialization { get; set;}
    [InverseProperty("Doctor")]
    public string Icollection<JrDoctor> childDoctors { get; set;}
}
public class JrDoctor : Entity
{
    public long? DoctorId { get; set;}
    [ForeignKey("DoctorId")]
    public virtual Doctor Doctor { get; set;}
    public long? JuniorDoctorId { get; set;}
    [ForeignKey("JuniorDoctorId")]
    public virtual Doctor JuniorDoctor { get; set;}
}