You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 15:15:25