Search code examples
.net-coreentity-framework-coredomain-driven-designentity-framework-core-migrationsentity-framework-core-3.1

Auto-generated FK relations in EF Core - how to made them non-nullable


I have the following model:

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

public class Parent
{
    public int Id { get; set; }
    public List<Child> Childs { get; set; }
}

Without any further instructing, EF Core 3.1 automatically infers the reference relation between Parent and Child, and generates the following migration creating nullable foreign key column on Child table:

....

migrationBuilder.CreateTable(
        name: "Child",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("SqlServer:Identity", "1, 1"),
            ParentId = table.Column<int>(nullable: true)   // <--- !!
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Child", x => x.Id);
            table.ForeignKey(
                name: "FK_Child_Parent_ParentId",
                column: x => x.ParentId,
                principalTable: "Parent",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);
        });

resulting in the schema below:

enter image description here

I need the FK to be non-nullable though. How to enforce EF to do it without changing the model (without the necessity of introducing artificial properties only to define underlying storage relations)?


PS: In particular I want to avoid abusing the model by introducing 2-way references, only to be able to express what I need, e.g.

public class Child
{
    public int Id { get; set; }
    public Parent Parent { get; set; }   // <--- not acceptable
}

modelBuilder.Entity<Parent>()
    .HasMany(p => p.Childs)
    .WithOne(c => c.Parent)
    .IsRequired();   // <--- non-null

Is the manual interference into the migration code the only solution (doesn't it result in mismatch with the model snapshot then)?


Solution

  • Since the dependent entity has no reference navigation property on which to put [Required] attribute or use C# 8 non nullable reference type (e.g. Parent vs Parent?), and has no explicit FK property with non nullable type (e.g. int vs int?), the only remaining option is fluent API.

    Relationship fluent API requires at least correct Has + With pair, and then in this particular case IsRequired() method:

    modelBuilder.Entity<Parent>()
        .HasMany(e => e.Childs) // collection navigation property
        .WithOne() // no reference navigation property
        .IsRequired();