级联删除与实体框架 - 由EF删除的相关实体

Nit*_*amk 29 entity-framework cascading-deletes

我在实体框架中删除了一个问题.简而言之,EF显式尝试从数据库中删除实体,即使我已经明确地将EF配置为在数据库中使用级联删除.

我的设计:

我有三种实体类型MainEntity,EntityTypeAEntityTypeB.EF已经配置在删除时使用级联删除EntityTypeAEntityTypeB.换句话说,如果我删除了一个实例MainEntity,我希望删除所有相关EntityTypeAEntityTypeB实例.我从不删除EntityTypeAEntityTypeB不删除他们的父母.

我的问题是EF明确地发出了一个DELETE声明EntityTypeA,导致我的应用程序崩溃.

这就是我的模型:

这些关系具有以下非默认配置:

  • 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)
Run Code Online (Sandbox Code Playgroud)

我的代码:

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

怎么了

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

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

这会导致外键违规,因为EntityTypeB的表中有一些项引用了EntityTypeA实例.

为什么Entity Framework会为EntityTypeA实例发出显式删除,即使我已将Entity Framework配置为使用级联删除?如果我删除Include("EntityTypeA"),它将再次开始工作.

Lad*_*nka 41

这正是级联删除行为在EF中的表现.在EF设计器中为关系设置级联指示EF DELETE为每个已加载的相关实体执行语句.它没有ON CASCADE DELETE在数据库中说什么.

使用EF时设置级联删除需要两个步骤:

  • 在EF设计师中设置Cascade关系.这指示必须在删除父实体之前删除所有已加载的相关实体的上下文.如果不发生这种情况,EF将抛出异常,因为内部状态将检测到加载的子级与任何现有父级实体无关,即使需要该关系.我不确定在执行父实体的删除语句之前或之后是否发生这种情况但没有区别.EF在执行修改后不会重新加载相关实体,因此它根本不知道数据库中触发的级联删除.
  • ON CASCADE DELETE在数据库中设置关系.这将指示SQL删除在删除父项时未加载到上下文的所有相关记录.

EF中级联删除的实现很奇怪且效率很低,但这就是它的行为方式,如果你想使用它,你必须修改你的应用程序才能在这种情况下正常运行.

  • 感谢您的回复!(当我生成我的数据库模型sql脚本时,如果我在我的实体数据模型中启用了级联,则EF在SQL语句中包含ON CASCADE DELETE,所以我认为EF会依赖于此.) (2认同)

Ωme*_*Man 5

也可以在数据库中的FK约束上设置级联删除,而不是在EF设计器上.

以下是Sql Server Management Studio(SSMS)关于如何设置级联删除的可视步骤.

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

在此输入图像描述

我在我的博客上更深入地讨论了这个问题:Entity Framework Cascading Deletes; 从数据库中设置它.