繁体   English   中英

EF Core:一对实体之间的一对一和一对多关系

[英]EF Core: One-to-one and One-to-many Relationships Between a Single Pair of Entities

下面是我希望使用 EF Core model 访问的一些实体的简化表示。 Company可以与其Manager建立可选的一对一关系,也可以与其Employee建立一对多关系。

public class Company
{
    public int Id { get; set; }
    public virtual ICollection<Employee> Employees { get; set; }
    public virtual Manager Manager {  get; set; }
    public int? ManagerId {  get; set; }
}

public class Employee
{
    public int Id { get; set; }
    public virtual Company Company {  get; set; }
    public int CompanyId {  get; set; }
}

public class Manager : Employee
{
}

实体以通常的方式暴露给 EF Core:

public DbSet<Company> Companies { get; set; }

public DbSet<Employee> Employees { get; set; }

我曾尝试过model他们的关系,如下:

modelBuilder.Entity<Company>()
    .HasMany(item => item.Employees)
    .WithOne(item => item.Company)
    .HasForeignKey(item => item.CompanyId)
    .IsRequired(true);

modelBuilder.Entity<Manager>()
    .HasOne(item => item.Company)
    .WithOne(item => item.Manager)
    .HasForeignKey<Company>(item => item.ManagerId)
    .IsRequired(false);

但是,在运行时,EF Core 拒绝此配置并显示消息“无法在 'Company.Manager' 和 'Employee.Company' 之间创建关系,因为 'Company.Employees' 和 'Employee.Company' 之间已经存在关系。导航可以只参与单个关系。如果要覆盖现有关系,请首先在“OnModelCreating”中的导航“Employee.Company”上调用“Ignore”。

谁能建议如何配置它? 非常感谢。

当用另一个实体扩展现有的具体实体时,扩展的 class 字段将添加到同一个表中,因此您可以在一行中确定哪个员工也是经理。 这称为按层次结构表 (TPH)。

您想要的是每个类型的表 (TPT) 模式 - 尚未由开箱即用的实体提供。 更多关于那些在这里!

要在此之前自行设置,请“完全由流利的 api”定义模型,这样您就可以创建自己的关系,而无需使用实体约定。

像这样的东西(即使没有构建,它是一个记事本涂鸦)

public class Employee {
    public string EmployeeId {get;set;}
    public string DisplayName {get;set;}

    public string WorksAtCompanyId {get;set;}
    public Company WorksAtCompany {get;set; }

    public string ManagesCompanyId {get;set;}
    public Company ManagesCompany {get;set; }

}

modelBuilder.Entity<Employee>()
b.Property<string>("EmployeeId").HasMaxLength(36).HasColumnType("nvarchar(36)");
b.Property<string>("DisplayName").HasColumnType("nvarchar(max)");
b.Property<string>("WorksAtCompanyId").HasColumnType("nvarchar(max)");
b.Property<string>("ManagesCompanyId").HasColumnType("nvarchar(max)");

b.HasOne(d => d.WorksAtCompany).WithMany(d => d.Employees).HasPrincipalKey<Employee>(d => d.WorksAtCompanyId).HasForeignKey<Company>(d => d.CompanyId).IsRequired().OnDelete(DeleteBehavior.Restrict);
b.HasOne<Company>(d => d.ManagesCompany).WithOne<Employee>(d => d.Manager).HasPrincipalKey<Employee>(d => d.ManagesCompanyId).HasForeignKey<Company>(d => d.CompanyId).OnDelete(DeleteBehavior.Restrict);


public class Company {
    public string CompanyId {get;set;}
    public List<Employee> Employees {get;set;}

    public string ManagerId {get;set;}
    public Employee Manager {get;set;}
}

modelBuilder.Entity<Company>()
b.Property<string>("CompanyId").HasMaxLength(36).HasColumnType("nvarchar(36)");
b.Property<string>("DisplayName").HasColumnType("nvarchar(max)");

b.HasMany(d => d.Employees).WithOne<Employee>(d => d.WorksAtCompany).HasPrincipalKey<Employee>(d => d.WorksAtCompanyId).HasForeignKey<Company>(d => d.CompanyId).OnDelete(DeleteBehavior.Restrict);
b.HasOne(d => d.Manager).WithOne(d => d.ManagesCompany).HasPrincipalKey<Employee>(d => d.ManagesCompanyId).HasForeignKey<Company>(d => d.CompanyId).OnDelete(DeleteBehavior.Restrict);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM