c# - EF Core DB-first:如何在没有级联删除的情况下删除依赖项?
问题描述
(示例代码贴在最后。)
我使用的是 EF Core 5数据库优先(即反向工程 POCO)。当使用 '删除' 集合中的项目时.Remove()
,后续SaveChanges()
会抱怨孤儿。是的,可以找到很多关于此的问答。
对于代码优先方案,可以将其添加到配置中(从这里):
modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });
但对于 DB-first 来说是不切实际的。如果数据库为 FK 关系设置了级联删除(此处的文档参考),则生成的模型 [更正]不包括
entity.OnDelete(DeleteBehavior.ClientSetNull)
并且删除(使用.Remove()
)确实有效,包括SaveChanges()
. 但 ...
我在这里面临的问题是,这个“解决方案”要求我们所有的 FK 关系都在数据库中配置了级联删除。哎呀!数据完整性对我们很重要,并且使用 UNIQUE 约束和不可空的 FK 关系来保护它之前已经拯救了我们。没有设置级联删除是一种类似的保护措施,并且仅将其用于切断关系的情况可以说是矫枉过正。
因此,转到第三个选项:显式删除孤立的子项,注意我在此处描述的第二个项目符号中。我所需要的只是旧的ObjectContext.DeleteObject()
,但没有等效的 EF Core。
问:如何删除该子项?如果不可能,我还有其他选择吗?
这是一个在代码中将其变为现实的快速示例:
//Create a parent with two children
var db = new Context();
var newParent = new Parent() {Name = "NewParent"+DateTime.Now.Second};
db.Parents.Add(newParent);
newParent.Children = new List<Child>() {new Child() {Name="ChildOne"}, new Child() {Name="ChildTwo"}};
db.SaveChanges();
db.Dispose();
//Pick a parent item and delete one child item
var db2 = new Context();
var Parent = db2.Parents.First();
db2.Entry(Parent).Collection(f => f.Children).Load();
var ChildToDelete = Parent.Children.First();
Parent.Children.Remove(ChildToDelete);
db2.SaveChanges(); // -----> FAILS with "The association between entity types 'Parent'
// and 'Child' has been severed, but the relationship is either marked
// as required or is implicitly required because the foreign key
// is not nullable."
桌子基本上是
CREATE TABLE [dbo].[Child](
[ChildId] [int] IDENTITY(1,1) NOT NULL,
[ParentId] [int] NOT NULL,
[Name] [nchar](20) NOT NULL,
CONSTRAINT [PK_Child] PRIMARY KEY CLUSTERED)
CREATE TABLE [dbo].[Parent](
[ParentId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nchar](20) NOT NULL,
CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED)
ALTER TABLE [dbo].[Child] WITH CHECK ADD CONSTRAINT [FK_Child_Parent] FOREIGN KEY([ParentId])
REFERENCES [dbo].[Parent] ([ParentId])
ALTER TABLE [dbo].[Child] CHECK CONSTRAINT [FK_Child_Parent]
解决方案
而不是从父的集合中删除子
Parent.Children.Remove(ChildToDelete);
删除孩子
db.Set<Child>().Remove(ChildToDelte);
推荐阅读
- amazon-web-services - 为什么存在角色和政策?
- php - Laravel 5.6 - Auth 在共享主机中不起作用
- c# - 将 ParameterizedThreadStart 重构为 Async Await
- assembly - 多个子程序无法返回主程序
- prestashop - Prestashop 模块 ProductComments
- android - SeTransactionSyncTask:检索帐户时出错 java.lang.IllegalStateException:没有当前的触碰付款帐户
- html - 为什么 `display:table-cell` 使 `margin:0 auto` 无效?
- python-3.x - pycryptodome:MAC 检查失败(使用decrypt_and_verify)
- python - pandas.setindex() 到日期时间的问题
- perl - Perl“使用未初始化的值”