C#中使用Action修改实体失效:原因分析与修复方案
问题原因
- EF Core的变更跟踪依赖实体实例:你从数据库加载的
entity是被DbContext跟踪的实例,但后续entity = entityAsModel.ToEntity()会创建一个全新的未被跟踪的实例,替换变量后,原跟踪实例的属性根本没被修改,DbContext只会关注它最初跟踪的那个实例,所以SaveChangesAsync不会生成任何更新语句。 ToEntity()方法生成的是新对象,而非修改原跟踪实例的属性,导致EF无法感知到变更。
修复方案
核心思路是修改原跟踪实体的属性,而非替换实体实例。你需要将修改后的Model属性映射回最初加载的那个被跟踪的entity上,而不是重新赋值变量。
修改后的代码示例:
public async Task UpdateAsync(string uri, Action<Models.RequestObject> modify, CancellationToken cancellationToken = default) { Entities.RequestObject entity = _dbContext.RequestObjects.Local.SingleOrDefault(p => p.Uri == uri) ?? await _dbContext.RequestObjects.Where(p => p.Uri == uri).SingleOrDefaultAsync(cancellationToken); if (entity != null) { Models.RequestObject entityAsModel = entity.ToModel(); modify.Invoke(entityAsModel); // 将修改后的Model属性映射回原跟踪实体 // 方式1:使用现成的属性映射方法(推荐,避免手动赋值出错) entity.MapFromModel(entityAsModel); // 方式2:手动逐个赋值(如果没有现成映射方法) // entity.Title = entityAsModel.Title; // entity.Description = entityAsModel.Description; // ... 其他需要更新的属性 await _dbContext.SaveChangesAsync(cancellationToken); } }
说明
- 原代码中的
AsTracking()可以省略,因为EF Core默认查询就是跟踪状态(除非全局配置了AsNoTracking)。 - 不管用映射方法还是手动赋值,只要修改的是原跟踪实体的属性,EF的变更跟踪就会检测到这些变化,在
SaveChangesAsync时自动生成对应的UPDATE语句,只更新被修改的属性。
内容的提问来源于stack exchange,提问作者Szyszka947
相关产品推荐
相关产品推荐

