Entity Framework 中的级联删除 - EF 删除相关实体

29
我在Entity Framework中遇到了删除问题。简而言之,即使我已经明确地配置EF使用数据库中的级联删除,EF仍然会明确地尝试从数据库中删除实体。
我的设计:
我有三种实体类型,MainEntity、EntityTypeA和EntityTypeB。 EF已被配置为在删除EntityTypeA和EntityTypeB时使用级联删除。换句话说,如果我删除MainEntity的一个实例,则希望所有相关的EntityTypeA和EntityTypeB实例也被删除。我永远不会删除EntityTypeA或EntityTypeB而不删除它们的父级。
我的问题是,EF明确地针对EntityTypeA发出DELETE语句,导致我的应用程序崩溃。
这是我的模型长这样:

以下是关系的非默认配置:

  • MainEntity -> EntityTypeA OnDelete: Cascade
  • MainEntity -> EntityTypeB OnDelete: Cascade

关系EntityTypeA -> EntityTypeBOnDelete: None

数据库内容

INSERT INTO MainEntities (Name) values ('Test')
insert into EntityTypeA (MainEntityID) VALUES (1)
insert into EntityTypeB (MainEntityID, EntityTypeAId) VALUES (1, 1)
insert into EntityTypeB (MainEntityID, EntityTypeAId) VALUES (1, 1)

我的代码:

class Program
{
   static void Main(string[] args)
   {
      var context = new Model1Container();
      var mainEntity = context.MainEntities.Include("EntityTypeA").SingleOrDefault();
      context.DeleteObject(mainEntity);
      context.SaveChanges();
   }
}

发生了什么

当我调用SaveChanges时,Entity Framework会在数据库中执行以下操作:

exec sp_executesql N'delete [dbo].[EntityTypeA]
where ([Id] = @0)',N'@0 int',@0=1

这会导致外键冲突,因为EntityTypeB的表中有引用EntityTypeA实例的项目。
问题:为什么即使我配置了Entity Framework使用级联删除,它仍会对EntityTypeA实例发出显式删除?如果我删除Include("EntityTypeA"),它就开始正常工作了。

12
模型的图像不可用。 - flipchart
2个回答

41
这正是EF中级联删除的行为。在EF设计器中设置关系上的"Cascade"指示EF执行每个加载的相关实体的“DELETE”语句。它并没有涉及数据库中的“ON CASCADE DELETE”。
在使用EF时设置级联删除需要两步:
1. 在EF设计器中设置关系上的"Cascade"。这会通知上下文,在删除父实体之前必须删除所有已加载的相关实体。如果这不发生,EF将抛出异常,因为内部状态将检测到加载的子项与任何现有的父实体都不相关,即使关系是必需的。我不确定这是否会在父实体的删除语句执行之前或之后发生,但没有区别。EF不会在执行修改后重新加载相关实体,因此它根本不知道在数据库中触发的级联删除。
2. 在数据库中的关系上设置"ON CASCADE DELETE"。这将指示SQL删除所有相关记录,这些记录在删除父记录时未加载到上下文中。
EF中级联删除的实现方式很奇怪且效率低下,但这就是其行为方式。如果想要使用它,必须修改应用程序以正确处理此情况。

2
谢谢您的回复!(当我生成数据库模型 SQL 脚本时,如果我在实体数据模型中启用了级联,EF 将在 SQL 语句中包含 ON CASCADE DELETE,因此我认为 EF 将依赖于此。) - Nitramk

5

除了在EF设计器中设置外,还可以在数据库中的FK约束上设置级联删除。

以下是在Sql Server Management Studio(SSMS)上设置级联删除的视觉步骤。

注意完成后,在尝试删除之前不要忘记针对数据库更新edmx。

enter image description here

我在我的博客中更深入地讨论了这个问题:Entity Framework Cascading Deletes; Set it from the database.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接