更新Book集合项时并发错误引发异常:预期影响1行实际影响0行
问题原因及解决方案
问题根源
直接替换book.Highlights集合的操作(book.Highlights = newHighlights)会让EF Core尝试删除所有原有Highlight实体,再批量插入新实体。但连续执行移除+添加操作时,EF的变更跟踪可能出现偏差:比如原有Highlight的跟踪状态异常,或者EF生成的删除语句对应的数据库记录已不存在,导致执行删除时触发“预期影响1行实际0行”的异常。
正确的集合更新方式
不要直接替换集合,而是通过对比原有集合和DTO中的新集合,逐个处理增删改:
修改后的Highlights处理代码
case "Highlights": { // 1. 找出需要删除的原有Highlight(不在新集合中的项) var highlightsToRemove = book.Highlights .Where(existing => !bookUpdateDto.Highlights.Any(dto => dto.Id == existing.HighlightId)) .ToList(); foreach (var highlight in highlightsToRemove) { book.Highlights.Remove(highlight); } // 2. 找出需要添加的新Highlight(不在原有集合中的项) foreach (var dtoHighlight in bookUpdateDto.Highlights) { var existingHighlight = book.Highlights.SingleOrDefault(h => h.HighlightId == dtoHighlight.Id); if (existingHighlight == null) { // 新增Highlight book.Highlights.Add(_mapper.Map<Highlight>(dtoHighlight)); } else { // 如果需要更新已有Highlight的属性,在这里处理 _mapper.Map(dtoHighlight, existingHighlight); } } continue; }
关键说明
- 这种方式让EF Core能正确跟踪每个实体的变更状态(删除/新增/修改),不会出现批量操作时的跟踪偏差。
- 确保DTO中的Highlight包含唯一标识(比如
Id),用于匹配原有实体和新实体。 - 如果Highlight有需要更新的属性,通过
_mapper.Map(dtoHighlight, existingHighlight)直接更新已有实体,避免重复删除插入。
额外排查点
- 检查
Highlight实体的主键配置是否正确,EF能否正确识别唯一标识。 - 确认
LoadRelationShipsAsync方法是否正确加载了book.Highlights集合(确保是跟踪状态的实体)。
内容的提问来源于stack exchange,提问作者Creapermann
相关产品推荐
相关产品推荐

