EF Core - SaveChanges 上没有数据库更新

Posted

技术标签:

【中文标题】EF Core - SaveChanges 上没有数据库更新【英文标题】:EF Core - no database update on SaveChanges 【发布时间】:2021-02-26 12:15:57 【问题描述】:

今天我有点惊讶我的 DbContext 的 SaveChanges() 方法没有按预期工作。

这是我用来从 Db 获取用户数据的方法:

        public async Task<UserModel> GetUserByIdAsync(string Id, bool editMode)
        
            if (editMode) return await UserDbContext.Users.FirstOrDefaultAsync(usr => usr.UserId == Id);
            else return await UserDbContext.Users.AsNoTracking().FirstOrDefaultAsync(usr => usr.UserId == Id);
        

这是应该在 Db 中更新实体的方法:

        public async Task<bool> UpdateUserDataByAsync(UserModel updatedUser, ClaimsPrincipal currentUser)
        
            var user = await GetUserByIdAsync(updatedUser.UserId, true);
            user = updatedUser;
            return await UserDbContext.SaveChangesByAsync(currentUser) > 0;
        

另外,SaveChangesByAsync 方法只是被覆盖 SaveChanges() 以自动更新一些 Db 列,例如 UpdatedBy

public async Task<int> SaveChangesByAsync(ClaimsPrincipal userPrincipal,
                                         CancellationToken cancellationToken = new CancellationToken())
        
            try
            
                DateTime now = DateTime.UtcNow;
                var entries = ChangeTracker
                    .Entries()
                    .Where(e => e.Entity is BaseModel && (
                            e.State == EntityState.Added
                            || e.State == EntityState.Modified));

                foreach (var entityEntry in entries)
                
                    ((BaseModel)entityEntry.Entity).UpdatedDate = now;
                    ((BaseModel)entityEntry.Entity).UpdatedBy = userPrincipal.FindFirstValue("UserId") ?? "Anonymous";

                    if (entityEntry.State == EntityState.Added)
                    
                        ((BaseModel)entityEntry.Entity).CreatedDate = now;
                        ((BaseModel)entityEntry.Entity).CreatedBy = userPrincipal.FindFirstValue("UserId") ?? "Anonymous";
                    
                

                return await base.SaveChangesAsync(cancellationToken);
            
            catch (TaskCanceledException)
            
                return await Task.FromCanceled<int>(cancellationToken);
            

        

最终我通过将UpdateUserDataByAsync更改为以下内容克服了这个问题:

            UserDbContext.Entry(await GetUserByIdAsync(updatedUser.UserId, true)).CurrentValues.SetValues(updatedUser);
            return await UserDbContext.SaveChangesByAsync(currentUser) > 0;

但是我想问你为什么初始版本不起作用?由于用户在没有AsNoTracking() 修饰符的情况下被拉出,上下文不应该继续跟踪任何变化吗,在这种情况下是用updatedUser 数据简单地替换user 数据?

谢谢!

【问题讨论】:

user = updatedUser; 会覆盖引用,但不会触发更改跟踪。 @HenkHolterman,谢谢!那么这种方法是否只有在我知道哪些属性已更改以避免直接手动更新用户时才有用?在所有其他情况下我应该选择CurrentValues.SetValues吗? 【参考方案1】:

你可以让你的代码更简单:

public async Task<bool> UpdateUserDataByAsync(UserModel updatedUser, ClaimsPrincipal currentUser)
        
 UserDbContext.Entry(updatedUser).State = EntityState.Modified;
 return await UserDbContext.SaveChangesByAsync(currentUser) > 0;

【讨论】:

谢谢。那么UserDbContext.Entry(updatedUser) 将如何找到需要更新的正确用户?它是否通过 Id 检查? 是的,它使用泛型重载函数来查找对象的类型和 ID。仅当您的实体具有主键时,它才能正常工作。

以上是关于EF Core - SaveChanges 上没有数据库更新的主要内容,如果未能解决你的问题,请参考以下文章

如果在 Db 上修改了先前加载的实体,如何将 EF 设置为不让 saveChanges?

ef的savechanges最多执行多少条数据

EF6 - Update()失败,多个SaveChangeAsync,但没有多个SaveChanges()

.NET Core 2 - EF Core 错误处理 保存更改

EF Core性能优化

EF Core 是不是支持 TransactionScope?