删除EF6中的本地子实体和DB子实体

本文关键字:实体 DB EF6 删除 | 更新日期: 2023-09-27 18:13:03

使用实体框架6,我有主和细节实体。我有一个WinForm,它在网格中显示给定主实体的详细数据。上下文在表单的整个生命周期内被保存。

使用BindingList:

将详细列表绑定到网格。
detailBindingSource = new BindingSource();
detailBindingList = new BindingList<Detail>(master.Details);
detailBindingSource.DataSource = detailBindingList;
detailGrid.SetDataBinding(detailBindingSource, "");

当用户删除网格中的一行时,下面的代码删除了详细信息(注释是我对认为代码所做的事情的解释):

var row = detailGrid.GetRow();         // Get the currently selected row in the detail grid
var detail = (Detail)row.DataRow;      // Get the entity related to the row
row.Delete();                          // This will delete the line from the list, but not from the DB
if (detail.ID > 0)                     // Don't try to delete a row that's only been added in memory and not to the DB
    dbset.Remove(detail);              // This will mark the entity to be deleted from the DB

当用户完成时,更改将被保存:

context.SaveChanges();

如果我删除现有行并保存,则所有工作正常。如果我删除在表单/上下文的生命周期内添加的行并保存,则一切都可以正常工作。但是,如果我同时删除现有行和删除新添加且尚未保存的行,则在保存时会得到以下异常:

系统。InvalidOperationException:操作失败:不能更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性被设置为空值。如果外键不支持空值,则必须定义一个新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

搜索有关异常的信息,我发现了一些关于如何从父实体的导航列表中删除不足以删除实体本身的引用,但我认为在上面的代码中调用Remove解决了这个问题(并且似乎如果我只删除现有行)。

有谁知道为什么只有在删除每种类型(新类型和旧类型)的行时才会发生异常?

删除EF6中的本地子实体和DB子实体

在所有三个测试中要删除的现有行是否相同?我的意思是,它是同一行,有相同的底层数据,相同的关系吗?似乎在第三个测试中,您正在删除的现有行与另一个表有关系,该表本身与第三个表有不可空的关系。当关系消失时,第三个表上对应的行也需要被删除。

如果您创建并删除了上下文,就不会有问题。不要使用全局上下文

这并不能回答错误发生的原因(或者可能在某些情况下为什么没有发生错误),但是解决方案是分离数据库中没有的新添加的行:

if (detail.ID > 0)
    dbset.Remove(detail);
else
    dbset.Detach(detail);