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

Entity Framework中ThenInclude过滤及结合AutoMapper ProjectTo的实现

解决方案

问题1:Include/ThenInclude过滤不生效的原因及修复

你最初的代码未过滤SectorBenchmark,是因为EF Core中过滤Include集合的特性需要EF Core 5.0+版本支持,且必须触发查询执行(如调用ToList())。未执行查询时仅构建了查询对象,不会应用过滤逻辑;添加ToList()后查询执行,过滤规则才会生效,这也是你后续解决该问题的核心原因。

正确的EF Core过滤Include写法(确保版本符合要求):

var filteredBenchmarks = _dbContext.ProjectBenchmarks
    .Where(pb => pb.ProjectId == targetProjectId) // 先过滤目标项目的基准
    .Include(b => b.GlobalBenchmark)
        .ThenInclude(gb => gb.SectorBenchmarks.Where(sb => sb.SectorId == sectorId))
    .ToList();

问题2:结合AutoMapper的ProjectTo实现过滤+映射

当使用ProjectTo进行DTO投影时,不能依赖Include/ThenInclude的过滤逻辑(因为ProjectTo会生成独立的SELECT语句,忽略Include中的过滤规则),可通过以下两种方式实现需求:

方式1:映射配置中传入动态参数(推荐)

在AutoMapper配置中定义支持动态参数的映射,查询时传入行业ID:

  1. 配置映射规则:
CreateMap<GlobalBenchmark, GlobalBenchmarkDTO>()
    .ForMember(dest => dest.SectorBenchmarks, opt => opt.MapFrom((src, _, __, context) => 
        src.SectorBenchmarks.Where(sb => sb.SectorId == (int)context.Items["SectorId"])));

CreateMap<ProjectBenchmark, ProjectBenchmarkDTO>()
    .IncludeMembers(pb => pb.GlobalBenchmark);
  1. 执行带参数的投影查询:
var sectorId = targetProjectSectorId; // 项目所属行业ID
var result = _dbContext.ProjectBenchmarks
    .Where(pb => pb.ProjectId == targetProjectId)
    .ProjectTo<ProjectBenchmarkDTO>(_mapper.ConfigurationProvider, 
        opt => opt.Items["SectorId"] = sectorId)
    .ToList();

方式2:手动投影过滤

直接在查询中手动构建DTO,显式过滤SectorBenchmark,无需依赖AutoMapper的集合映射规则:

var sectorId = targetProjectSectorId;
var result = _dbContext.ProjectBenchmarks
    .Where(pb => pb.ProjectId == targetProjectId)
    .Select(pb => new ProjectBenchmarkDTO
    {
        // 映射ProjectBenchmark字段
        Id = pb.Id,
        Name = pb.Name,
        // ...其他字段
        GlobalBenchmark = new GlobalBenchmarkDTO
        {
            Id = pb.GlobalBenchmark.Id,
            Name = pb.GlobalBenchmark.Name,
            // ...其他字段
            SectorBenchmarks = pb.GlobalBenchmark.SectorBenchmarks
                .Where(sb => sb.SectorId == sectorId)
                .Select(sb => new SectorBenchmarkDTO
                {
                    Id = sb.Id,
                    SectorId = sb.SectorId,
                    // ...其他字段
                }).ToList()
        }
    })
    .ToList();

内容的提问来源于stack exchange,提问作者Lukas Grecu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:17:44