问题描述
我正在尝试将DeleteBehavior
从Cascade
更改为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和更高版本中有四个可用选项,如下所示:
- 无操作
- 级联
- 设置为空
- 设置默认值
将CONSTRAINT添加到FOREIGN KEY中的步骤
打开新查询窗口
[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
无操作设置的结果
当您改回到``层叠''模式时
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将被删除。
如果您的数据库正在使用 SQL Server Management Studio(SSMS),它将更加容易。
→右键单击表设计,然后转到“关系”,然后在左侧窗格中选择外键,然后在右侧窗格中,展开菜单“插入和更新规范”,然后选择“限制”作为“删除规则”。