c# - 仅执行 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;
}
}
解决方案
也许这是一个有点晚的帖子,但是......我建议将代码从模型分离到数据库访问,在你的情况下,要更新的对象是类本身的一个实例。我要做的是创建一个名为 WorkLogDAL 的类并复制和更改方法 EndEdit(WorkLog workLog) 然后 else 方法将类似于:
else
{
db.TimeTrackerWorklog.Attach(workLog);
db.Entry(workLog).State = EntityState.Modified;
db.SaveChanges();
}
推荐阅读
- c - 在 TCP 服务器中使用 pthread_create 时出现错误 11
- java - 如何将 JComboBox 中的项目与其他数据相关联?
- javascript - 开玩笑在 Expo 上运行时无法识别 .jsx 文件
- c++ - Cuda 元素数大于分配的线程数
- haskell - isPalindrome 的 Haskell 单子
- python - 计算矩形的平均颜色并进行比较。开放式CV
- themes - 如何将购物车图标添加到 shopify 流线主题中的标题菜单?
- git - WSL 的 git ssh 无法连接到我们公司的私有内部 git 主机
- r - R - 遍历 2 个列表并返回一个列表
- asp.net - ASP.NET 找不到类型或命名空间“Greeting”