简体   繁体   中英

How to configure one-to-one relationship in EF Core with FK on both ends

I have following entities:

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
}

So each subscription might have only one billing contract and each billing contract belongs to a single subscription.

I'm trying to configure this relationship in my 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);

But from the generated migration(or from the snapshot or from the actual DB schema) I can tell that only FK in Subscription table is created. I cannot make EF to create a FK(and index) in the BillingContract table. I also tried to use annotation attributes with the same result.

Did I miss something? Or it's a bug in EF?

I'm using EF Core 2.2

To eliminate a possibility of a corrupted db snapshot I created a brand new console project using EF Core 3.1. After adding initial migration I have the same result with missing 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");
}

This is not an EF bug. Usually, two tables have an association relationship, and you only need to create one foreign key in one of the tables. The two-way foreign key is for the entity and does not exist in the database design. This docuement has give the detail example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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