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.
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