【发布时间】:2023-02-19 05:45:36
【问题描述】:
我有以下型号
public partial class Parent
{
public int IdParent { get; set; }
public virtual ICollection<FirstChild> FirstChild{ get; set; } = new List<FirstChild>();
}
public partial class FirstChild
{
public int IdFirstChild { get; set; }
public virtual ICollection<SecondChild> SecondChild { get; set; } = new List<SecondChild>();
}
public partial class SecondChild
{
public int IdSecondChild { get; set; }
public virtual ICollection<ThirdChild> ThirdChild{ get; set; } = new List<ThirdChild>();
}
public partial class ThirdChild
{
public int IdThirdChild { get; set; }
public String SomeProperty{ get; set; }
}
我用这种方式更新Parent所有它的关系:
var parentDB = _context.Parent.Single(x => x.IdParent == {id})
.Include(x => x.FirstChild)
.ThenInclude(x => x.SecondChild)
.ThenInclude(x => x.ThirdChild);
parentDb.FirstChild = {newCollectionValuesList}
_context.SaveChanges();
这适用于 EF Core 6:
- 如果在
{newCollectionValuesList}中,parentDb.FirstChild中已经存在一个元素(相同 ID),它会更新(及其所有层次结构) - 如果if不存在,会添加
- 如果它存在但未在
{newCollectionValuesList}中指定,它将被删除
当我升级到 EF Core 7 时,我开始遇到这个错误:
无法跟踪实体类型“SecondChild”的实例,因为已跟踪具有键值“{IdSecondChild: XXXX}”的另一个实例。附加现有实体时,确保只附加一个具有给定键值的实体实例
我在查询中添加了
.AsNoTracking()来解决这个问题,但是删除不起作用(当{newCollectionValuesList}不包含数据库中存在的元素时,不会被删除)我不想手动遍历所有关系并手动添加条件来更新子元素
我在What's new in EF7、Breaking changes in EF7 和之前的 SO 问题中都没有找到与此相关的任何内容
这是一个带有集成测试的sample project来重现问题
【问题讨论】:
-
你能发一个 minimal reproducible example 因为当前代码甚至不应该编译。
-
这更有可能是由于数据不同于 EF 版本。看起来
newCollectionValuesList包含多个具有相同密钥的SecondChild实例,或者一个与已附加实例具有相同密钥的实例。 -
完全一样的数据。我在集成测试中发现了这个错误(不是通过手动测试)。所以输入是完全一样的
-
为什么这个例子不应该编译?
-
我添加了一个示例项目来重现问题