我正在使用带有Repository模式的EF6(存储库有自己的上下文实例)。当我使用FindAsync
获取和修改实体时,不会跟踪更改,因此编辑的所有属性都不会保存在SaveChanges
上。但是,我还通过IQueryable
通过存储库公开表,如果我以这种方式获取实体,则所有更改都会正确保存。我试图弄清楚为什么在使用FindAsync方法时不会跟踪更改。
我的Find repo方法:
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; }
}
通过Find访问路径(修改后不保存更改):
routeRepo.FindDrivingRouteAsync(message.RouteId, message.UserId);
通过公开的IQueryable访问路由(在修改时保存更改):
routeRepo.Routes.FirstOrDefault(r => r.RouteId == message.RouteId && r.CDCUserInfoId == message.UserId);
我确定我错过了一些东西(对EF来说有点新),所以任何帮助都会非常感谢,谢谢!
答案 0 :(得分:0)
我刚遇到这个问题 - 我怀疑这是EF的一个错误,因为手动更新了EntityState&amp;然后强制上下文保存更改,或在同一个Microsoft EntityFramework库中使用相同方法的同步版本,没有引起任何问题。
具体来说,使用 Microsoft.AspNet.Identity.EntityFramework 库&amp; UserStore / UserManager类,当使用FindAsync检索对象时,实体框架未正确跟踪后续修改。
即。在FindAsync之后收到此错误,然后尝试更新数据库:
附加类型为“ MyNamespace.MyUser ”的实体失败,因为同一类型的另一个实体已具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图表,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。
我失败的UpdateAsync方法如下所示:
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);
}
..随后拾起了这些变化&amp;在数据库中自动更新。一个完全同步的Find&amp;更新(使用相同的库)也允许跟踪实体和&amp;更新 - 我认为这个解决方案比解决方案更不可接受。
我不是百分之百确定这是一个错误,但如果有足够的人验证这一点,有人应该用MSFT打开一张票。