EF Core migration generated `ReferentialAction.Restrict` but in context set as `DeleteBehavior.ClientSetNull`

c# entity-framework-core sql-server

Question

I discover this while I tried to run my delete query when it stop my with the error

The DELETE statement conflicted with the REFERENCE constraint "FK_List_ListId"

When I through an analysis to the issue, noticed that in the latest migration onDelete: ReferentialAction.Restrict. But I have generated this migration after set .OnDelete(DeleteBehavior.ClientSetNull).

Below by sample tables and their relationships:

public class List
{
    public int ListId { get; set; }
    public string ListName { get; set; }
    public ICollection<Task> Tasks { get; set; }
}

public class Task
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public string Description { get; set; }
    public int? ListId { get; set; }
    public List List { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Task>()
        .HasOne(x => x.List)
        .WithMany(y => y.Tasks)
        .HasForeignKey(z => z.ListId)
        .HasConstraintName("FK_List_ListId")
        .OnDelete(DeleteBehavior.ClientSetNull);
}

Migration code generated as:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.DropForeignKey(
        name: "FK_List_ListId",
        table: "Tasks");

    migrationBuilder.AddForeignKey(
        name: "FK_List_ListId",
        table: "Tasks",
        column: "ListId",
        principalTable: "Lists",
        principalColumn: "ListId",
        onDelete: ReferentialAction.Restrict);
}

In migration onDelete: ReferentialAction.Restrict but should not it be onDelete: ReferentialAction.SetNull. I am not sure what I did wrong while creating the relationship.

1
0
3/31/2020 5:36:22 PM

Accepted Answer

EF Core 2.0.1 metadata and migrations use different enums for specifying the delete behavior - respectively DeleteBehavior and ReferentialAction. While the first is well documented, the second and the mapping between the two is not (at the time of writing).

Here is the current mapping:

DeleteBehavior    ReferentialAction
==============    =================
Cascade           Cascade
ClientSetNull     Restrict
Restrict          Restrict
SetNull           SetNull

In your case, the relationship is optional, hence the DeleteBehavior by convention is ClientSetNull which maps to onDelete: Restrict, or in other words, enforced (enabled) FK w/o cascade delete.

If you want different behavior, you have to use fluent API, e.g.

modelBuilder.Entity<BigAwesomeDinosaurWithTeeth>()
    .HasMany(e => e.YummyPunyPrey)
    .WithOne(e => e.BigAwesomeDinosaurWithTeeth)
    .OnDelete(DeleteBehavior.SetNull); // or whatever you like
21
1/30/2018 1:58:18 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow