【问题标题】:How to configure one-to-one relationship in EF Core with FK on both ends如何在两端使用 FK 在 EF Core 中配置一对一关系
【发布时间】:2021-04-25 01:15:45
【问题描述】:

我有以下实体:

public class Subscription
{
    public int Id { get; set; }

    public int? BillingContractId { get; set; }
    public BillingContract BillingContract { get; set; }

    //other properties
}

public class BillingContract 
{
    public int Id { get; set; }

    public int SubscriptionId { get; set; }
    public Subscription Subscription { get; set; }

    //other properties
}

因此,每个订阅可能只有一个计费合同,并且每个计费合同属于一个订阅。

我正在尝试在我的 dbcontext 中配置这种关系:

builder.Entity<Subscription>()
    .HasOne(subscription => subscription.BillingContract)
    .WithOne(billingContract => billingContract.Subscription)
    .HasForeignKey<BillingContract>(billingContract => billingContract.SubscriptionId)
    .IsRequired(true);

builder.Entity<BillingContract>()
    .HasOne(billingContract => billingContract.Subscription)
    .WithOne(subscription => subscription.BillingContract)
    .HasForeignKey<Subscription>(subscription => subscription.BillingContractId)
    .IsRequired(false);

但是从生成的迁移(或从快照或从实际的数据库模式)我可以看出只有 Subscription 表中的 FK 被创建。我无法让 EF 在 BillingContract 表中创建 FK(和索引)。我还尝试使用具有相同结果的注释属性。

我错过了什么吗?还是 EF 的 bug?

我使用的是 EF Core 2.2

为了消除数据库快照损坏的可能性,我使用 EF Core 3.1 创建了一个全新的控制台项目。添加初始迁移后,我得到与缺少 FK 相同的结果:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "BillingContracts",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("SqlServer:Identity", "1, 1"),
            SubscriptionId = table.Column<int>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_BillingContracts", x => x.Id);
        });

    migrationBuilder.CreateTable(
        name: "Subscriptions",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("SqlServer:Identity", "1, 1"),
            BillingContractId = table.Column<int>(nullable: true)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Subscriptions", x => x.Id);
            table.ForeignKey(
                name: "FK_Subscriptions_BillingContracts_BillingContractId",
                column: x => x.BillingContractId,
                principalTable: "BillingContracts",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);
        });

    migrationBuilder.CreateIndex(
        name: "IX_Subscriptions_BillingContractId",
        table: "Subscriptions",
        column: "BillingContractId",
        unique: true,
        filter: "[BillingContractId] IS NOT NULL");
}

【问题讨论】:

  • 关系原理很简单:1个FK == 1个关系,2个FK == 2个关系等等。所以在这种情况下,2个FK中的一个是多余的,应该删除,具体取决于哪个实体关系的主体。可以保留导航属性。

标签: entity-framework entity-framework-core ef-core-2.2


【解决方案1】:

这不是 EF 错误。通常,两张表是有关联关系的,只需要在其中一张表中创建一个外键即可。双向外键用于实体,在数据库设计中不存在。这个docuement已经给出了详细的例子。

【讨论】:

  • @Roman Koliada,你能接受这个答案,还是有其他问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
  • 2021-12-29
  • 2022-01-22
  • 2021-05-30
  • 2018-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多