c# - 仅执行 db.SaveChanges() 时如何修复 "The instance of entity type XXX cannot be tracked"

标签 c# .net wpf ef-core-2.1

我在实现 IEditable 的对象的 EndEdit 函数上有以下代码:

    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 在上下文中显示一个实体,状态为已修改,这正是我所期望的。但是,当我在执行 else block 后调用 db.SaveChanges 时,我收到以下错误消息:

The instance of entity type 'Worklog' cannot be tracked because another instance with the key value '{Id: b8476f6e-aab6-408f-ab75-f4944b9a0262}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

这是否与我试图将 IEditable 对象直接保存到数据库中这一事实有关?

super 困惑,欢迎任何帮助!

堆栈跟踪:

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; }
}

View 模型:

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;
    }
}

最佳答案

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

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

关于c# - 仅执行 db.SaveChanges() 时如何修复 "The instance of entity type XXX cannot be tracked",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53481302/

相关文章:

c# - 如何为.NET Core项目指定程序集版本?

c# - 在 asp.net 中更改 gridview 的自动生成的选择列的文本 - 如何?

C#/WPF - DesignData - 绑定(bind)到 DesignData 集合属性

c# - 如何从 webBrowser 控件中的当前选定选项获取 innerText

c# - 异步 WCF 方法 WebOperationContext 在等待后为 null

c# - 生成后事件执行 PowerShell

c# - 如何为具有集合的模型创建 View 模型

c# - 周期性处理中的膨胀线程问题

c# - 警告 CS0618 : 'IPAddress.Address' is obsolete: 'This property has been deprecated

c# - 使 WPF 文本框边距可单击/可选择