29

我在实体框架中遇到了删除问题。简而言之,即使我已明确将 EF 配置为在数据库中使用级联删除,EF 也会显式尝试从数据库中删除实体。

我的设计:

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

我的问题是 EF 明确发出DELETEfor 的语句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)

我的代码:

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 配置为使用级联删除,为什么 Entity Framework 仍会为 EntityTypeA 的实例发出显式删除?如果我删除 Include("EntityTypeA") 它会再次开始工作。

4

2 回答 2

41

这正是 EF 中级联删除的行为方式。在 EF 设计器中对关系设置CascadeDELETE会指示 EF为每个加载的实体执行语句。它没有ON CASCADE DELETE在数据库中说明任何内容。

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

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

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

于 2011-03-27T11:13:16.057 回答
5

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

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

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

在此处输入图像描述

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

于 2015-05-28T14:41:44.397 回答