EF Core中关联子表批量删除数据问题求助
EF Core 删除子表多行数据问题的解决方法
问题根源
你当前代码的核心问题在于:
- 将数据库查询到的实体转成DTO后,又重新映射成新的
ProcessingGroupDetail对象,这些新对象没有被EF Core上下文跟踪,调用删除方法不会触发数据库操作。 - 后续执行
mapper.Map(request.processingGroupDto, processingGroupDb)时,会覆盖processingGroupDb的导航属性,导致之前的删除逻辑被冲掉。
修正方案
直接操作EF上下文跟踪的数据库实体,无需经过DTO来回映射:
public async Task<bool> Handle(SaveProcessingGroupCommand request, CancellationToken cancellationToken) { if(request.processingGroupDto.ProcessingGroupID > 0) { var processingGroupDb = await processingGroupRepository.GetProcessingGroupAndDetails(request.processingGroupDto.ProcessingGroupID); if (processingGroupDb is not null) /// Update { // 直接操作数据库实体的导航属性,无需转DTO if (processingGroupDb.ProcessingGroupDetailsNavigation.Count > 0) { var requestDetailIds = request.processingGroupDto.ProcessingGroupDetailsNavigation .Select(x => x.ProcessingGroupDetailID) .ToHashSet(); // 用HashSet提升查询效率 // 筛选出数据库中存在,但请求里没有的明细项 var detailsToDelete = processingGroupDb.ProcessingGroupDetailsNavigation .Where(x => !requestDetailIds.Contains(x.ProcessingGroupDetailID)) .ToList(); if (detailsToDelete.Count > 0) { // 直接从导航集合中移除,或者调用仓库的删除方法(取决于仓库实现) foreach (var detail in detailsToDelete) { processingGroupDb.ProcessingGroupDetailsNavigation.Remove(detail); // 如果仓库的Delete方法是跟踪实体的,也可以用: // await processingGroupDetailRepository.DeleteAsync(detail); } } } // 映射更新剩余属性(此时导航属性已经处理好删除) mapper.Map(request.processingGroupDto, processingGroupDb); await processingGroupRepository.UpdateAsync(processingGroupDb); } } else /// Add { var processingGroup = mapper.Map<ProcessingGroup>(request.processingGroupDto); processingGroup.DynamicYN = false; await processingGroupRepository.InsertAsync(processingGroup); } return await processingGroupRepository.UnitOfWork.SaveDataAsync(); }
额外说明
- 如果你的
DeleteItemsAsync方法需要接收被跟踪的实体,直接传递从processingGroupDb导航属性中筛选出的对象即可,不需要重新映射。 - 使用
HashSet存储请求中的ID可以大幅提升Contains方法的查询效率,尤其是当明细数量较多时。 - 确保仓库的
UpdateAsync方法只是标记实体为修改状态,而非重新创建实体,避免上下文跟踪失效。
内容的提问来源于stack exchange,提问作者Shah Nazmul
相关产品推荐
相关产品推荐

