EF Core 表之间的一对一关系

EF Core One to One Relationionship between tables

在 EF Core 中,我首先设置了两个对象和流畅的代码

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public PlatForm Platform { get; set; }
}

public class Platform
{
    public int Id { get; set; }
    public string PlatformName { get; set; }
    public Customer Customer { get; set; }
}

modelBuilder.Entity<Platform>(entity =>
{
    entity.ToTable("Platform").HasKey(e => e.Id);
    entity.HasOne(t => t.Customer)
    .WithOne(t => t.Platform)
    .HasForeignKey<Customer>(t => t.Id).IsRequired();   
});



modelBuilder.Entity<Customer>(entity =>
{
    entity.ToTable("Customer");
    entity.Property(e => e.Name).HasPrecision(50).IsRequired().HasColumnName("name");
});

添加平台时,您应该select 为其所属的客户。 您可以添加客户没有平台不能添加没有客户的平台

当我尝试添加客户时出现异常

the property is also part of a foreign key for which the principal entity in the relationship is not known.

“您可以在没有平台的情况下添加客户,但不能在没有客户的情况下添加平台。”

这表示一对 0 或 1 的关系或本质上是受限的 many-to-one,其中平台将包含与其相关的客户的 FK (CustomerId):

为 FK 实施阴影 属性:

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public PlatForm Platform { get; set; }
}

public class Platform
{
    public int Id { get; set; }
    public string PlatformName { get; set; }
    public Customer Customer { get; set; }
}

modelBuilder.Entity<Platform>(entity =>
{
    entity.ToTable("Platform").HasKey(e => e.Id);
    entity.HasOne(t => t.Customer)
    .WithOne(t => t.Platform)
    .HasForeignKey<Platform>("CustomerId").IsRequired();   
});

架构会将其视为 many-to-one,从技术上讲,没有任何东西可以阻止您尝试创建引用同一客户的第二个平台,但就 EF 域而言,一个客户可以有 0-1 个平台,一个平台需要有 1 个客户。将关系建立为聚合根 where-by 通常是个好主意,您不要将平台称为 top-level 实体,只能通过客户访问它。 (没有平台 DbSet 在 DbContext 中公开)

使用 EF Core,您还可以探索将其设置为客户下的“拥有”关系,它可以采用相同的架构或在客户下嵌入平台实体字段 table。这加强了实体之间的聚合根关系。

modelBuilder.Entity<Customer>(entity =>
{
    entity.ToTable("Customer").HasKey(e => e.Id);
    entity.OwnsOne(t => t.Platform)
    .HasForeignKey<Platform>("CustomerId");   // <- not sure if this is needed
});

我不是 100% 跨所有关系,但对于 EF Core 3.1+,它确实支持单独的 table 关系,我认为这是关系可选的要求。 (0-1 平台)使用 OwnsOne 而不是 HasOne/WithOne 的优势在于,这限制了 EF 允许通过 DbSet 或使用 Set<Platform> 访问拥有的实体.使用 HasOne,一些后来的编码人员可以尝试通过添加一个平台 DbSet 或执行类似以下操作来“破解”没有 Platforms DbSet:

var customer = context.Customers.Single(x => x.Id == customerId);
var platform = new Platform { Customer = customer };
context.Set<Platform>().Add(platform);
context.SaveChanges();

这会产生各种后果,因为加载的客户可能已经关联了一个平台,即使不是急切加载,引用也可能会被加载并替换为可能不是预期的代码。对于 Owned 关系,不允许使用此代码。