使用FindAsync时,EF6不跟踪实体的更改

时间:2014-12-08 22:52:41

标签: c# entity-framework repository-pattern

我正在使用带有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来说有点新),所以任何帮助都会非常感谢,谢谢!

1 个答案:

答案 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打开一张票。