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 有些陌生(,所以任何帮助将不胜感激,谢谢!

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

我刚刚遇到了这个问题 - 我怀疑这是 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 开票。