首先将EF Core代码中的DeleteBehavior从Cascade更改为Restrict

问题描述

我正在尝试将DeleteBehaviorCascade更改为Restrict 我正在使用EF核心进行迁移。

这就是使用级联删除行为迁移的样子

migrationBuilder.CreateTable(
            name: "ElementsPerStrip",columns: table => new
            {
                ......
            },constraints: table =>
            {
                table.PrimaryKey("PK_ElementsPerStrip",x => x.Id);
                table.ForeignKey(
                    name: "FK_ElementsPerStrip_Strips_StripId",column: x => x.StripId,principalTable: "Strips",principalColumn: "Id",onDelete: ReferentialAction.Cascade);
            });

此后进行了一些迁移,现在我需要将ReferentialAction还原为Restrict

这是我的Strip模型的样子:

public class Strip
{
    public int Id { get; set; }
    public int ProjectId { get; set; }
    public int ScriptId { get; set; }
    public virtual Script Script { get; set; }
    public int SceneId { get; set; }        
    ...
    public virtual ICollection<ElementPerStrip> ElementPerStrip { get; set; }
}

这是我的ElementPerStrip的外观:

 public class ElementPerStrip
{
    public int Id { get; set; }
    ...
    public int StripId { get; set; }
    // public virtual Strip strip { get; set; } // issue is here
}

,并且在modelbuilder中,我添加了此内容以尝试更改Deletebehavior以限制:

builder.Entity<Strip>()
        .HasMany(c => c.ElementPerStrip)
        .WithOne()
        .HasForeignKey(c => c.StripId)
        .OnDelete(DeleteBehavior.Restrict);

它创建的迁移对我来说是正确的:

  migrationBuilder.DropForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",table: "ElementsPerStrip");

        migrationBuilder.AddForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",table: "ElementsPerStrip",column: "StripId",onDelete: ReferentialAction.Restrict);

但是当我运行我的应用程序并尝试删除测试条时,出现以下错误:

The DELETE statement conflicted with the REFERENCE constraint "FK_ElementsPerStrip_Strips_StripId". The conflict occurred in database "MDb",table "dbo.ElementsPerStrip",column 'StripId'.

我无法删除StripId列,因为我需要用于过滤应用程序中的数据。 我如何解决这个问题,即我断开了两个表的连接,但保留了数据,但是更改了Deletebehaviour。

解决方法

要使用 EF 迁移更改删除行为,您必须删除并重新创建外键。

在包管理器控制台中,使用 Add-Migration 命令创建一个新的空迁移,然后像这样填写 Up 方法:

        migrationBuilder.DropForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",table: "ElementsPerStrip");
        migrationBuilder.AddForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",table: "ElementsPerStrip",column: "StripId",principalTable: "Strips",principalColumn: "Id",onDelete: ReferentialAction.Restrict);

为了完整起见,在 Down 方法中执行相反的操作:

        migrationBuilder.DropForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",onDelete: ReferentialAction.Cascade);

请注意:忽略任何通过 SSMS 修改数据库架构的建议。执行此操作的那一刻,您就搞砸了迁移策略,其重点是让您通过构建/部署管道控制架构,并始终使架构与代码保持一致。

,

SQL Server Server 2005和更高版本中有四个可用选项,如下所示:

  • 无操作
  • 级联
  • 设置为空
  • 设置默认值

以下是更新和删除操作的效果摘要: enter image description here

将CONSTRAINT添加到FOREIGN KEY中的步骤

打开新查询窗口

enter image description here

[SQL] 添加CONSTRAINT

ALTER TABLE [dbo].[ToDoItem]
   ADD CONSTRAINT FK_Delete_NoAction
   FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) ON DELETE No Action ON UPDATE No Action

点击绿色箭头执行enter image description here

无操作设置的结果

enter image description here


当您改回到``层叠''模式时
ALTER TABLE [dbo].[ToDoItem]
   DROP CONSTRAINT [FK_Delete_NoAction]

ALTER TABLE [dbo].[ToDoItem]
   ADD CONSTRAINT FK_Delete_Cascade
   FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) ON DELETE Cascade ON UPDATE Cascade

删除用户后,ToDoItem将被删除。

enter image description here




如果您的数据库正在使用 SQL Server Management Studio(SSMS),它将更加容易。

→右键单击表设计,然后转到“关系”,然后在左侧窗格中选择外键,然后在右侧窗格中,展开菜单“插入和更新规范”,然后选择“限制”作为“删除规则”。

SQL Server Management Studio

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...