EF Core迁移会以错误的方向为一对多关系在级联删除时添加级联

时间:2019-11-12 15:20:56

标签: c# entity-framework-core

我正在使用asp.net core 3 web apiEF core 3,我在两个表之间有一个one to many关系:

TaskTaskType

Task有一个TaskType

TaskType有很多Tasks

这是2个实体:

public class TaskType
{
    public TaskType() {
        Tasks = new HashSet<Task>();
    }

    [Key]
    public Guid TaskTypeID { get;set; }
    ...
    public ICollection<Task> Tasks { get; set; }
} 

public class Task
{
    public Task() {

    }

    [Key]
    public Guid TaskID {get;set;}
    ...
    public Guid TaskTypeID { get; set; }
    [ForeignKey("TaskTypeID")]
    public TaskType TaskType { get; set; }
}

当我运行add-migration命令时,它将生成此代码

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.AddColumn<Guid>(
        name: "TaskTypeID",
        table: "Task",
        nullable: false,
        defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));

    migrationBuilder.CreateIndex(
        name: "IX_Task_TaskTypeID",
        table: "Task",
        column: "TaskTypeID");

    migrationBuilder.AddForeignKey(
        name: "FK_Task_TaskType_TaskTypeID",
        table: "Task",
        column: "TaskTypeID",
        principalTable: "TaskType",
        principalColumn: "TaskTypeID",
        onDelete: ReferentialAction.Delete);// I want to change this to ReferentialAction.NoAction
}

protected override void Down(MigrationBuilder migrationBuilder)
{
    migrationBuilder.DropForeignKey(
        name: "FK_Task_TaskType_TaskTypeID",
        table: "Task");

    migrationBuilder.DropIndex(
        name: "IX_Task_TaskTypeID",
        table: "Task");

    migrationBuilder.DropColumn(
        name: "TaskTypeID",
        table: "Task");
}

请注意,onDelete: ReferentialAction.Delete行显然是错误的,应该以另一种方式级联。

要解决此问题,我想将其更改为ReferentialAction.NoAction

并在上下文中将此代码添加到我的onModelCreating

modelBuilder.Entity<TaskType>()
            .HasMany(c => c.Tasks)
            .WithOne(e => e.TaskType)
            .OnDelete(DeleteBehavior.Cascade);

这是为一对多关系添加级联删除的正确方法吗?我应该修改生成的迁移代码,还是有另一种方法告诉我在删除TaskType时不要级联删除Task

编辑: 接受的答案帮助我提出了解决方案。我应该更具体一些,我需要孤立的TaskType记录。因此,我将TaskTypeID FK设置为​​可为空的Guid,并在我的OnDelete()中将选项设置为ReferentialAction.SetNull

1 个答案:

答案 0 :(得分:3)

方向正确。

如果要通过从删除const f = new Frame("z"); f.content = null; // error, can't assign to read only function acceptFrame(f: Frame) { f.content = null; // error here too } 的级联来删除Task,则很可能会留下很多孤立的TaskType记录(假设没有参照完整性)

实体TaskType依赖于TaskType实体,因此删除Task的唯一有效方案是删除所有关联的Task记录。

解决此问题的一种常用方法是使用 soft 删除。

本质上为实体添加属性

TaskType

,您便可以知道已删除实体,但仍保留正确的引用。