EF6 在使用 FindAsync 时不跟踪实体上的更改
本文关键字:实体 跟踪 FindAsync EF6 | 更新日期: 2023-09-27 18:33:32
我正在使用EF6,带有存储库模式(存储库有自己的上下文实例(。当我使用 FindAsync
获取和修改实体时,不会跟踪更改,因此编辑的任何属性都不会保存在SaveChanges
上。但是,我也通过存储库公开表 IQueryable
,如果我以这种方式获得实体,则所有更改都会正确保存。我试图弄清楚为什么在使用 FindAsync 方法时不跟踪更改。
我的查找存储库方法:
public async Task<CDCRoute> FindDrivingRouteAsync(long routeId, string userId)
{
var route = await routeContext.Routes.FindAsync(routeId);
if (route != null && route.CDCUserInfoId == userId)
{
return route;
}
return null;
}
表暴露与 IQueryable:
public IQueryable<CDCRoute> Routes
{
get { return routeContext.Routes; }
}
通过查找访问路由(修改时不保存更改(:
routeRepo.FindDrivingRouteAsync(message.RouteId, message.UserId);
通过暴露的 IQueryable 访问路由(修改时会保存更改(:
routeRepo.Routes.FirstOrDefault(r => r.RouteId == message.RouteId && r.CDCUserInfoId == message.UserId);
我确定我错过了一些东西(对 EF 有些陌生(,所以任何帮助将不胜感激,谢谢!
我刚刚遇到了这个问题 - 我怀疑这是 EF 的错误,因为手动更新 EntityState 然后强制上下文保存更改,或者在同一Microsoft EntityFramework 库中使用同一方法的同步版本,没有引起任何问题。
具体来说,当使用 Microsoft.AspNet.Identity.EntityFramework 库和 UserStore/UserManager 类时,当使用 FindAsync 检索对象时,实体框架无法正确跟踪后续修改。
即在 FindAsync 之后收到此错误,然后尝试更新数据库:
附加类型为">MyNamespace.MyUser"的实体失败,因为相同类型的另一个实体已具有相同的主键值。使用"附加"方法或将实体的状态设置为"未更改"或"已修改"(如果图形中的任何实体具有冲突的键值(时,可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,请使用"添加"方法或"已添加"实体状态来跟踪图形,然后根据需要将非新实体的状态设置为"未更改"或"已修改"。
失败的更新异步方法如下所示:
public async Task UpdateAsync(MyUser user)
{
var result = await _manager.UpdateAsync(user); //State = EntityState.Unchanged
//UpdateAsync above is directly inherited from Microsoft.AspNet.Identity.EntityFramework.UserManager<T>
//ERROR! Primary key duplicate (Default identity method doing Attach :/ )
}
最终,通过跟踪,我发现即使进行了更改,EntityState 仍然"未更改"。然后我把代码改成这样:
public async Task UpdateAsync(MyUser user)
{
_store.Context.Entry(user).State = EntityState.Modified;
var result = await _store.Context.SaveChangesAsync();
//var result = await _manager.UpdateAsync(user);
}
..然后,这些更改在数据库中被拾取并自动更新。完全同步的查找和更新(使用相同的库(也允许跟踪和更新实体 - 我认为这个解决方案比解决方法更不能接受。
我不是 100% 确定这是一个错误,但如果这被足够多的人验证,应该有人使用 MSFT 开票。