【问题标题】:EF Core already tracked entity with same idEF Core 已跟踪具有相同 ID 的实体
【发布时间】:2021-04-07 14:50:52
【问题描述】:

我不知道如何摆脱错误:

无法跟踪实体类型“关系”的实例,因为已在跟踪另一个具有键值“{Id: 26}”的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。

我尝试将实体从上下文中分离出来,但即使这样也不能阻止此错误的发生。有人可以指出我做错了什么吗?

服务:

private async Task<int> EditAsync(RelationModel model)
{
    RelationEntity entity = _mapper.ToEntity(model);
    RelationEntity oldRelation = await _relationRepository.GetRelationAsync(entity.Id);
    _relationRepository.UpdateRelation(oldRelation, entity);
    await _relationRepository.SaveAsync();
    return entity.Id;
}

存储库:

    public void UpdateRelation(Relation oldRelation, Relation relation)
    {
        if (oldRelation != null)
        {
            // Detach
            Context.Entry(oldRelation).State = EntityState.Detached;

            // Delete childs
            if (oldRelation.Person != null && relation.Person == null)
            {
                Context.Persons.Remove(oldRelation.Person);
            }

            if (oldRelation.Customer != null && relation.Customer == null)
            {
                Context.Customers.Remove(oldRelation.Customer);
            }

            if (oldRelation.Supplier != null && relation.Supplier == null)
            {
                Context.Suppliers.Remove(oldRelation.Supplier);
            }

            if (oldRelation.Employee != null && relation.Employee == null)
            {
                Context.Employees.Remove(oldRelation.Employee);
            }

            // Update parent
            Context.Relations.Update(relation); // <-- error occurs
        }
    }

Relation实体:

public class Relation : BaseEntity<int>
{
    public string Code { get; set; }

    public int? PersonId { get; set; }
    public Person Person { get; set; }

    public int? CompanyId { get; set; }
    public Company Company { get; set; }

    public int? CustomerId { get; set; }
    public Customer Customer { get; set; }

    public int? SupplierId { get; set; }
    public Supplier Supplier { get; set; }

    public int? EmployeeId { get; set; }
    public Employee Employee { get; set; }

    public ICollection<RelationRelations> ParentRelations { get; set; }
    public ICollection<RelationRelations> ContactPersons { get; set; }
    public ICollection<RelationContactMethod> ContactMethods { get; set; }
    public ICollection<RelationAddress> Addresses { get; set; }
}

更新

我尝试替换

Context.Relations.Update(relation); 

与

Context.Entry(oldRelation).CurrentValues.SetValues(relation);

但是我在 Relation 实体上的所有属性都没有更新。

更新 2

运行以下代码时

Context.Entry(oldRelation).CurrentValues.SetValues(relation);
Context.SaveChanges();

我可以看到旧关系已使用新值进行了更新,但它们并未应用于数据库...这是为什么呢?

【问题讨论】:

  • 不要更新您的relation,而是更新您的oldRelation。看起来这两种关系在技术上是“相同”的关系,但具有更新的值(因为这是一个编辑权?)。
  • 正确,但如何更新relation?我是否必须遍历每个属性?因为实体有很多属性,其中包含其他对象
  • 恐怕你必须这样做,但有一些方法可以通过创建一个类或方法来实现这一点。或者,我看到您正在使用映射器,因此将 EditAsync 方法中的 relation 参数映射到 oldRelation 可能是一个选项,然后保存您的旧关系。

标签: c# entity-framework .net-core entity-framework-core


【解决方案1】:

多年来,我一直在使用此代码而不是“更新”,所有内容始终正确更新,我从未出现任何错误。

尝试对 EF 使用通用代码绝不是一个好主意。如果要更新多个类,请尝试选择这种方式:

 var oldrelation = Context.Relations
.Include(i=> i.Person)
.Include(i=> i.Company)
...
.FirstOrDefault(i=> i.Id=entity.Id);

替换

 Context.Relations.Update(relation); 

与

Context.Entry(oldRelation).CurrentValues.SetValues(relation);

【讨论】:

  • 我已经试过了,你是对的,这不会出错。但是 Update 的问题在于它还更新了在(例如)Person 对象内部更改的属性。并且使用 Context.Entry 这些属性不会更新。那么当我使用 Context.Entry 时如何更新 Person 对象的属性呢?
  • 如果新关系中有一些额外的实体,则必须将它们包含在旧关系对象中。这样它将更新所有这些。
  • 但是在新旧实体上都有一个已经存在的属性(Relation.Code)。当我使用新值更改 Relation.Code 属性时,de DB 中的值不会使用您建议的那行代码进行更新。
  • 你能发布你的关系类吗?
  • 我已将其添加到我的帖子中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多