【问题标题】:EF Core DB-first: How to delete dependent item without cascade delete?EF Core DB-first:如何在没有级联删除的情况下删除依赖项?
【发布时间】:2021-07-22 03:24:48
【问题描述】:

(示例代码贴在最后。)

我使用的是 EF Core 5 database-first(即反向工程 POCO)。当使用.Remove()“删除”集合中的一个项目时,随后的SaveChanges() 会抱怨这个孤儿。是的,可以找到很多关于此的问答。

对于代码优先方案,可以将其添加到配置中(来自here):

modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });

但这对于 DB-first 来说是不实用的。如果数据库为FK关系(docs reference here)设置了级联删除,则生成的模型[更正]包含

entity.OnDelete(DeleteBehavior.ClientSetNull)

并且删除(使用.Remove()确实工作,包括SaveChanges()。但是……

我在这里面临的问题是,这个“解决方案”要求我们所有的 FK 关系都在数据库中配置了级联删除。哎呀!数据完整性对我们很重要,并且使用 UNIQUE 约束和不可空的 FK 关系来保护它之前已经拯救了我们。不设置级联删除是一种类似的保护措施,并且仅将其用于切断关系的情况可以说是矫枉过正。

所以,继续第三个选项:显式删除孤立的子项,注意我在here 描述的第二个项目符号中。我所需要的只是旧的 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]

【问题讨论】:

    标签: c# sql-server entity-framework-core


    【解决方案1】:

    而不是从父集合中删除子

    Parent.Children.Remove(ChildToDelete);
    

    删除孩子

    db.Set<Child>().Remove(ChildToDelte);
    

    【讨论】:

    • 哦! ICollection&lt;T&gt;.Remove(T)EntityFrameworkCore.DbSet&lt;T&gt;.Remove(T)。两个截然不同的Remove()'s
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 2018-07-19
    相关资源
    最近更新 更多