层级删除与实体框架相关实体由EF删除 [英] Cascading deletes with Entity Framework - Related entities deleted by EF

查看:148
本文介绍了层级删除与实体框架相关实体由EF删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Entity Framework中删除了一个问题。简而言之,EF明确地试图从数据库中删除一个实体,即使我已经明确地将EF配置为在数据库中使用级联删除。



我的设计:我有三个实体类型, MainEntity EntityTypeA EntityTypeB 。当删除 EntityTypeA EntityTypeB 时,EF已配置为使用级联删除。换句话说,如果我删除一个 MainEntity 的实例,我想要所有相关的 EntityTypeA EntityTypeB 要删除的实例。我不会删除 EntityTypeA EntityTypeB 而不删除其父级。



我的问题是,EF明确地为 EntityTypeA 发出 DELETE 语句,导致我的应用程序崩溃。 / p>

这是我的模型看起来像:





关系有以下非默认配置:



    imgur.com/KC43E.png/>
  • MainEntity - > EntityTypeA OnDelete:Cascade

  • MainEntity - > EntityTypeB OnDelete:Cascade



关系 EntityTypeA - > EntityTypeB OnDelete:无



数据库内容 / p>

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

我的代码

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

发生什么 p>

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

  exec sp_executesql N'delete [dbo]。[EntityTypeA] 
其中([Id] = @ 0)',N'@ 0 int',@ 0 = 1

这导致外键违规,因为EntityTypeB表中的项目引用了EntityTypeA实例。



问题



即使我已将Entity Framework配置为使用级联删除,Entity Framework为EntityTypeA实例发布显式删除?如果我删除了Include(EntityTypeA),它将再次开始工作。

解决方案

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



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




  • 设置EF设计器中的关联级联。在指定上下文之前,必须先删除所有加载的相关实体,然后才能删除该父实体。如果没有发生这种情况,EF将抛出异常,因为内部状态会检测到加载的子代与任何现有的父实体无关,即使需要关系。我不知道这是否在执行父实体的delete语句之前或之后发生,但没有区别。 EF在执行修改后不会重新加载相关实体,因此根本不了解数据库中触发的级联删除。

  • 设置 ON CASCADE DELETE 数据库中的关系。这将指示SQL在删除父级时删除所有未加载到上下文的相关记录。



在EF中执行级联删除是奇怪而且效率低下的,但这是它的行为方式,如果要使用它,则必须在此方案中修改应用程序才能正确执行。


I have an issue with deletion in Entity Framework. In short, EF explicitly tries to delete an entity from the database even though I've explcitly configured EF to use cascading deletes in the database.

My design:

I have three entity types, MainEntity, EntityTypeA and EntityTypeB. EF has been configured to use cascade deletion when deleting EntityTypeA and EntityTypeB. In other words, if I delete an instance of MainEntity, I want all related EntityTypeA and EntityTypeB instances to be deleted as well. I never delete EntityTypeA or EntityTypeB without also deleting their parent.

My problem is that EF explictly issues a DELETE statement for EntityTypeA, which causes my application to crash.

This is what my model look like:

The relations have the following non-default config:

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

The relation EntityTypeA -> EntityTypeB has OnDelete: None

Database contents

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)

My code:

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

What happens

When I call SaveChanges, Entity Framework executes the following in the database:

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

This causes an foreign key violation, because there are items in EntityTypeB's table referencing EntityTypeA instances.

Question

Why does Entity Framework issue an explicit delete for the instance of EntityTypeA even though I've configured Entity Framework to use cascading deletes? If I remove the Include("EntityTypeA") it starts working again.

解决方案

This is exactly how cascading deletes behaves in EF. Setting Cascade on a relation in EF designer instructs EF to execute DELETE statement for each loaded realated entity. It doesn't say anything about ON CASCADE DELETE in the database.

Setting Cascade deletion when using EF needs two steps:

  • Set Cascade on relation in EF designer. This instruct context that all loaded related entities must be deleted prior to deletion of the parent entity. If this doesn't happen EF will throw exception because internal state will detect that loaded childs are not related to any existing parent entity even the relation is required. I'm not sure if this happens before execution of delete statement of the parent entity or after but there is no difference. EF doesn't reload related entities after executing modifications so it simply doesn't know about cascade deletes triggered in the database.
  • Set ON CASCADE DELETE on relation in database. This will instruct SQL to delete all related records which were not loaded to context in the time of deleting the parent.

The implementation of cascade deletes in EF is strange and quite inefficient but this is how it behaves and if you want to use it, you must modify your application to behaves correctly in this scenario.

这篇关于层级删除与实体框架相关实体由EF删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆