【问题标题】:EFCore update: The instance of entity type '' cannot be tracked because another instance with the key value '{ID: 0}' is already being trackedEFCore 更新:无法跟踪实体类型“”的实例,因为已在跟踪另一个具有键值“{ID:0}”的实例
【发布时间】:2021-06-15 20:51:21
【问题描述】:

这与我几天前的上一个问题有关:EF Core duplicate keys: The instance of entity type '' cannot be tracked because another instance with the key value '' is already being tracked

我使用context.ChangeTracker.TrackGraph 在插入数据时给予我更多控制权。插入过程效果很好,正如我对上述问题的回答所示。当我更新项目并尝试保存它们时会出现此问题。

我的主要模型如下(为简单起见已更改类型名称):

public class Model
{
    public List<Data1> List1 { get; set; }
    ...
}

Data1 看起来像这样:

public class Data1
{
    public string Name{ get; set; }
    ...
}

要更新到数据库,我使用这个:

            using var context = Factory.CreateDbContext();
context.ChangeTracker.TrackGraph(model, node =>
            {
                if (!(node.Entry.Entity.GetType().IsSubclassOf(typeof(EFChangeIgnore)) && node.Entry.IsKeySet)) //this is a workaround but it solves the pk problems I have been having
                {
                    node.Entry.State = EntityState.Modified;
                }
                else if (!node.Entry.IsKeySet)
                {
                    node.Entry.State = EntityState.Added;
                }
            });
            return await context.SaveChangesAsync();

这很有效,因为它可以防止插入我现有的实体(继承自EFChangeIgnore),并且可以很好地处理其他实体的更新和插入。但是,如果我在 List1 中有多个 Data 项目,则会收到错误消息:

The instance of entity type 'Data1' cannot be tracked because another instance with the key value '{ID: 0}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

我理解这个错误,但我不明白为什么它会出现在这种情况下。是的,这两个实体的 ID 都为零,但这只是因为它们尚未插入数据库。我在这里做错了什么?

【问题讨论】:

  • edit您的问题包含您拥有的完整源代码作为minimal reproducible example,其他人可以编译和测试。
  • 你确定要搞砸context.ChangeTracker.TrackGraph吗?使用TrackGraph() 方法的原因是什么?为什么不像其他人一样使用普通的Add()/Remove() 方法?
  • 如果我使用 add 然后我得到关键错误。 EF 核心无法区分我现有的不应更新的只读实体和已编辑的实体之间的区别。一旦我把它放在一起,我会用这个例子更清楚地解释。
  • 我发现我犯了一个错误...查看我的答案@Progman

标签: c# entity-framework-core change-tracking


【解决方案1】:

原来我的错误是由于括号放错了。去图吧。

在我的SaveChanges 中,我不小心否定了顶部的整个条件,因此应该修改的实体变成了添加,反之亦然。这导致我打算添加的多个 ID 为 0 的实体被标记为已修改。然后 EF 抱怨两个现有实体具有相同的 ID。

也就是这一行:

if (!(node.Entry.Entity.GetType().IsSubclassOf(typeof(EFChangeIgnore)) && node.Entry.IsKeySet))

现在变成(为了清楚起见交换了条件):

if (node.Entry.IsKeySet && (!node.Entry.Entity.GetType().IsSubclassOf(typeof(EFChangeIgnore))))

我现在的整个 SaveChanges 方法是:

using var context = Factory.CreateDbContext();
            context.ChangeTracker.TrackGraph(model, node => //all entities inheriting from EFChangeIgnore will not be touched by the change tracker. Other entities with keys will be modified, and items without keys will be added
            {
                if (node.Entry.IsKeySet && (!node.Entry.Entity.GetType().IsSubclassOf(typeof(EFChangeIgnore)))) //this is a workaround but it solves key duplication problems
                {
                    node.Entry.State = EntityState.Modified;
                }
                else if (!node.Entry.IsKeySet)
                {
                    node.Entry.State = EntityState.Added;
                }
            return await context.SaveChangesAsync();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-03
    • 2020-01-31
    • 2019-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    相关资源
    最近更新 更多