How to do EF Core One-to-One Bi-Directional mapping with both foreign keys?

Viewed 139

(Sort of like this old SO post, but for EF Core 2 or 3)

When I map two independent entities that have an optional 1-to-1 bi-directional navigation to each other, the migration generated by EF Core is missing one of the foreign keys I would expect to see.

I have the following classes:

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

        public ClassTwo ClassTwo { get; set; }
        public int? ClassTwoId { get; set; }
    }

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

        public ClassOne ClassOne { get; set; }
        public int? ClassOneId { get; set; }
    }

And the following mapping definition:

    public class ClassOneDbConfiguration : IEntityTypeConfiguration<ClassOne>
    {
        public void Configure(EntityTypeBuilder<ClassOne> builder)
        {
            builder.HasOne(e => e.ClassTwo)
                    .WithOne(e => e.ClassOne)
                    .HasForeignKey<ClassTwo>(e => e.ClassOneId)
                    .OnDelete(DeleteBehavior.SetNull);

            builder.HasIndex(e => e.ClassTwoId).IsUnique();
        }
    }

    public class ClassTwoDbConfiguration : IEntityTypeConfiguration<ClassTwo>
    {
        public void Configure(EntityTypeBuilder<ClassTwo> builder)
        {
            builder.HasOne(e => e.ClassOne)
                    .WithOne(e => e.ClassTwo)
                    .HasForeignKey<ClassOne>(e => e.ClassTwoId)
                    .OnDelete(DeleteBehavior.SetNull);

            builder.HasIndex(e => e.ClassOneId).IsUnique();
        }
    }

The migration generated by dotnet-ef migrations add CreateLinks gives (I created the tables in a separate migration to simplify):

            migrationBuilder.AddColumn<int>(
                name: "ClassOneId",
                table: "EntitiesTwo",
                nullable: true);

            migrationBuilder.AddColumn<int>(
                name: "ClassTwoId",
                table: "EntitiesOne",
                nullable: true);

            migrationBuilder.CreateIndex(
                name: "IX_EntitiesTwo_ClassOneId",
                table: "EntitiesTwo",
                column: "ClassOneId",
                unique: true);

            migrationBuilder.CreateIndex(
                name: "IX_EntitiesOne_ClassTwoId",
                table: "EntitiesOne",
                column: "ClassTwoId",
                unique: true);

            migrationBuilder.AddForeignKey(
                name: "FK_EntitiesOne_EntitiesTwo_ClassTwoId",
                table: "EntitiesOne",
                column: "ClassTwoId",
                principalTable: "EntitiesTwo",
                principalColumn: "Id",
                onDelete: ReferentialAction.SetNull);

Where is the Foreign Key creation for table EntitiesTwo? Without it, I cannot have the ON CASCADE SET NULL on it and may end up with invalid data in my DB.

I can ensure referential integrity in my code, sure, but can I have the foreign key on the DB as well?

0 Answers
Related