首页 > 解决方案 > 仅执行 db.SaveChanges() 时如何修复“无法跟踪实体类型 XXX 的实例”

问题描述

EndEdit我对实现的对象的功能有以下代码IEditable

    public void EndEdit()
    {
        using (var db = new Context())
        {
            if (Id == Guid.Empty)
            {
                db.Add(this);
                db.SaveChanges();
            }
            else
            {
                var worklog = db.Find<Worklog>(Id);
                worklog.Comment = Comment;
                worklog.JiraIssue = JiraIssue;
                worklog.Ticks = Ticks;
                worklog.StartDate = StartDate;
                db.SaveChanges();
            }
        }
    }

对对象执行编辑后,db.Entry在上下文中显示一个实体,其状态为已修改,这是我所期望的。但是,当我db.SaveChanges在执行 else 块后调用时,会收到以下错误消息:

无法跟踪实体类型“工作日志”的实例,因为已在跟踪另一个具有键值“{Id: b8476f6e-aab6-408f-ab75-f4944b9a0262}”的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。

这可能与我试图将IEditable对象直接保存到数据库中的事实有关吗?

超级困惑欢迎任何帮助!

堆栈跟踪:

at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Nullable`1 forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode node, Boolean force)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode node, TState state, Func`3 handleNode)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode node, TState state, Func`3 handleNode)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState entityState, Boolean forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.NavigationReferenceChanged(InternalEntityEntry entry, INavigation navigation, Object oldValue, Object newValue)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntryNotifier.NavigationReferenceChanged(InternalEntityEntry entry, INavigation navigation, Object oldValue, Object newValue)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectNavigationChange(InternalEntityEntry entry, INavigation navigation)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(IStateManager stateManager)
at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.DetectChanges()
at Microsoft.EntityFrameworkCore.DbContext.TryDetectChanges()
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at TimeTracker.ViewModels.WorklogViewModel.EndEdit() in C:\TimeTracker\ViewModels\WorklogViewModel.cs:line 120

实体类:

public class Worklog: IGuidEntity
{

    public Guid Id { get; set; }
    public DateTime StartDate { get; set; } = DateTime.Now;
    public string Comment { get; set; }
    public long Ticks { get; set; }
    public bool Completed { get; set; }
    public bool Published { get; set; }
    public virtual JiraIssue JiraIssue { get; set; }

    public virtual ICollection<TimeTrackerWorklog> OriginalWorklogs { get; set; }

    public virtual TimeTrackerWorklog UserModifiedWorklog { get; set; }
}

视图模型:

public class WorklogViewModel : Worklog, IEditableObject
{
    public void BeginEdit()
    {
        return;
    }

    public void EndEdit()
    {
        using (var db = new TimeTrackerContext())
        {
            if (Id == Guid.Empty)
            {
                db.Add(this);
                db.SaveChanges();
            }
            else
            {
                var worklog = db.Find<TimeTrackerWorklog>(Id);
                worklog.Comment = Comment;
                worklog.JiraIssue = JiraIssue;
                worklog.Ticks = Ticks;
                worklog.StartDate = StartDate;
                db.SaveChanges();
            }
        }
    }

    public void CancelEdit()
    {
        return;
    }
}

标签: c#.netwpfef-core-2.1

解决方案


也许这是一个有点晚的帖子,但是......我建议将代码从模型分离到数据库访问,在你的情况下,要更新的对象是类本身的一个实例。我要做的是创建一个名为 WorkLogDAL 的类并复制和更改方法 EndEdit(WorkLog workLog) 然后 else 方法将类似于:

else
{
   db.TimeTrackerWorklog.Attach(workLog);
   db.Entry(workLog).State = EntityState.Modified;
   db.SaveChanges();
}

推荐阅读