两个一对一关系的不规则迁移文件

问题描述 投票:0回答:1

我有三个类,它们应该将一个概念一对一地分成 3 个表。从字面上看,我想拼凑一张巨大的桌子。

class MainHolder
{
  public Guid Id { get; set; }
  public FirstPart FirstPart { get; set; }
  public SecondPart SecondPart { get; set; }
}
class FirstPart
{
  public Guid Id { get; set; }
  public string Title { get; set; }
}
class SecondPart
{
  public Guid Id { get; set; }
  public string Description { get; set; }
}

我正在设置上下文和关系如下。

public DbSet<MainHolder> Holders { get; set; }
public DbSet<FirstPart> FirstParts { get; set; }
public DbSet<SecondPart> SecondParts { get; set; }

protected override void OnModelCreating(ModelBuilder model)
{
  model.Entity<FirstPart>()
    .HasOne<MainHolder>()
    .WithOne(a => a.FirstPart)
    .HasForeignKey<MainHolder>();
  model.Entity<SecondPart>()
    .HasOne<MainHolder>()
    .WithOne(a => a.SecondPart)
    .HasForeignKey<MainHolder>();
}

当我创建迁移时,主要持有者包含 2 列 - 第一列是其自身的 ID,另一列是第二个实体的 ID 不是第一个实体。外键按预期设置:只是不完整的列。

migrationBuilder.CreateTable(name: "Holders", columns: table => new
{
  Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
  SecondPartId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
},
constraints: table =>
{
  table.PrimaryKey("PK_Holders", x => x.Id);
  table.ForeignKey(
    name: "FK_Holders_FirstParts_Id",
    column: x => x.Id,
    principalTable: "FirstParts",
    principalColumn: "Id",
    onDelete: ReferentialAction.Cascade);
  table.ForeignKey(
    name: "FK_Holders_SecondParts_SecondPartId",
    column: x => x.SecondPartId,
    principalTable: "SecondParts",
    principalColumn: "Id");
});

migrationBuilder.CreateTable(name: "FirstParts", columns: table => new
{
  Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
  Title = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table => { table.PrimaryKey("PK_FirstParts", x => x.Id); });

migrationBuilder.CreateTable(name: "SecondParts", columns: table => new
{
  Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
  Description = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table => { table.PrimaryKey("PK_SecondParts", x => x.Id); });

我注意到 FK 在命名和级联策略方面的设置略有不同。我无法终生解释为什么会发生这种情况,因为两个实体的声明和配置方式完全相同。

我错过了什么?

如果是由于管理多个一对一表的某种约定,那么我很遗憾找不到任何类型的文档。我担心实际上存在偏差,我只是想意识到这一点。帮助我理解。

c# entity-framework database-migration entity-framework-migrations one-to-one
1个回答
0
投票

尝试删除 .HasForegnKey 我认为 EF 可能会对此感到困惑,因为它期望每个关系在 MainHolder 上都有一个唯一的 FK,并为第一种情况使用默认 ID 并为第二种情况生成一个。默认情况下,两个表上的 PK 之间将建立一对一的关系,这看起来是您设置和期望的方式,因此只需为两者定义 HasOne.WithOne 就可以按预期工作。

HasForeignKey 通常用于 1 对 1 关系,在这种关系中,您希望在关系的一侧指定一个单独的外键。例如,如果您想要在 MainHolder 上使用 FirstPartId 而不是在 PK 上加入两者。默认行为是对两个表都使用 PK。我建议的另一个变化是从 MainHolder 的角度而不是从 First 和 Second 的角度定义一对一的关系。

所以代替:

model.Entity<FirstPart>()
   .HasOne<MainHolder>()
   .WithOne(a => a.FirstPart)
   .HasForeignKey<MainHolder>();
model.Entity<SecondPart>()
   .HasOne<MainHolder>()
   .WithOne(a => a.SecondPart)
   .HasForeignKey<MainHolder>();

使用

model.Entity<MainHolder>()
   .HasOne(a => a.FirstPart)
   .WithOne();
model.Entity<MainHolder>()
   .HasOne(a => a.SecondPart)
   .WithOne();

关于支持可选双向导航属性的规则在 EF 核心中有些不固定,因此如果 FirstPart 和 SecondPart 上没有“MainHolder”引用,WithOne 可能无法按预期工作。如果 EF Core 抱怨,解决方法通常是添加

protected
(或可能是
private
)引用。一对一关系通常受益于双向引用,其中 MainHolder 包含对 FirstPart 的引用,而 FirstPart 包含返回其 MainHolder 的引用。该导航属性不需要
ForeignKey
属性或在一对一关系的一部分时定义的映射。

© www.soinside.com 2019 - 2024. All rights reserved.