我在实体框架中删除了一个问题。简而言之,EF显式尝试从数据库中删除实体,即使我已经明确地将EF配置为在数据库中使用级联删除。
我的设计:
我有三种实体类型,MainEntity
,EntityTypeA
和EntityTypeB
。 EF已被配置为在删除EntityTypeA
和EntityTypeB
时使用级联删除。换句话说,如果我删除MainEntity
的实例,我也希望删除所有相关的EntityTypeA
和EntityTypeB
实例。我从不删除EntityTypeA
或EntityTypeB
而不删除其父级。
我的问题是EF明确地为DELETE
发出EntityTypeA
语句,导致我的应用程序崩溃。
这就是我的模型:
关系具有以下非默认配置:
MainEntity -> EntityTypeA OnDelete: Cascade
MainEntity -> EntityTypeB OnDelete: Cascade
关系EntityTypeA -> EntityTypeB
有OnDelete: 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”),它将再次开始工作。
答案 0 :(得分:41)
这正是级联删除行为在EF中的表现。在EF设计器中的关系上设置 Cascade 指示EF为每个已加载的相关实体执行DELETE
语句。它没有说明数据库中的ON CASCADE DELETE
。
使用EF时设置级联删除需要两个步骤:
ON CASCADE DELETE
。这将指示SQL在删除父级时删除未加载到上下文的所有相关记录。EF中级联删除的实现很奇怪且效率很低,但这就是它的行为方式,如果你想使用它,你必须修改你的应用程序才能在这种情况下正常运行。
答案 1 :(得分:5)
可以在数据库中的FK约束上设置级联删除,而不是在EF设计器上。
以下是Sql Server Management Studio(SSMS)关于如何设置级联删除的可视步骤。
注意完成后,在尝试删除之前,请不要忘记对数据库更新edmx 。
我在博客上更深入地讨论了这个问题:Entity Framework Cascading Deletes; Set it from the database.