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

如何使用AutoMapper将嵌套集合属性投影到DTO并返回投影集合?

问题:AutoMapper映射嵌套集合到DTO集合(支持EF服务器端投影)

需求:将源模型LargeEntity的List<ExampleModelContainer>类型属性ModelEntries,投影为目标模型LargeEntityDto的List<ExampleModelDto>类型属性Models,且要求大部分投影操作在EF服务器端完成。

源模型

public class ExampleModel
{
    public int Id { get; set; }
    public float Something { get; set; }
    public string Info { get; set; } = "";
}

public class ExampleModelContainer
{
    public int Id { get; set; }
    public ExampleModel Model { get; set; } = null!;
}

public class LargeEntity
{
    public int Id { get; set; }
    public List<ExampleModelContainer> ModelEntries { get; set; } = null!;
}

目标模型

public class ExampleModelDto
{
    public float Something { get; set; }
    public string Info { get; set; } = "";
}

public class LargeEntityDto
{
    public int Id { get; set; }
    public List<ExampleModelDto> Models { get; set; } = null!;
}

尝试的配置及异常

尝试通过定义ExampleModelContainer到ExampleModel的转换间接映射,但配置验证失败:

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        CreateMap<ExampleModel, ExampleModelDto>();
        
        // 尝试将容器转换为模型,再自动转为DTO,但失败
        CreateMap<ExampleModelContainer, ExampleModel>()
            .ConvertUsing(x => x.Model);
        
        CreateMap<LargeEntity, LargeEntityDto>()
            .ForMember(x => x.Models, 
                opt => opt.MapFrom(y => y.ModelEntries));
    }
}

异常信息:

Unhandled exception. AutoMapper.AutoMapperConfigurationException: The following member on AutoMapperExps.Models.LargeEntityDto cannot be mapped:
        Models
Add a custom mapping expression, ignore, add a custom resolver, or modify the destination type AutoMapperExps.Models.LargeEntityDto.
Context:
        Mapping to member Models from AutoMapperExps.Models.LargeEntity to AutoMapperExps.Models.LargeEntityDto
Exception of type 'AutoMapper.AutoMapperConfigurationException' was thrown.
   at AutoMapper.Configuration.ConfigurationValidator.AssertConfigurationIsValid(IEnumerable`1 typeMaps)
   at AutoMapper.Configuration.ConfigurationValidator.AssertConfigurationExpressionIsValid(IEnumerable`1 typeMaps)
   at AutoMapper.MapperConfiguration.AssertConfigurationIsValid()
   at Program.Main(String[] args) in D:\Experiments\AutoMapperExps\Program.cs:line 1

解决方案

直接在MapFrom中通过LINQ选择容器内的Model属性,结合已有的ExampleModel到ExampleModelDto的映射,既满足配置验证,又支持EF服务器端投影:

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        // 定义基础模型到DTO的映射,EF可解析该表达式
        CreateMap<ExampleModel, ExampleModelDto>();

        CreateMap<LargeEntity, LargeEntityDto>()
            .ForMember(dest => dest.Models, 
                // 直接从每个容器中提取Model,AutoMapper会自动应用ExampleModel→ExampleModelDto的映射
                opt => opt.MapFrom(src => src.ModelEntries.Select(container => container.Model)));
    }
}

说明

  1. 避免自定义转换:之前使用ConvertUsing的方式会生成客户端评估代码,无法被EF转换成SQL,同时AutoMapper无法自动将List<ExampleModelContainer>转换为List<ExampleModelDto>,导致配置验证失败。
  2. 服务器端投影支持:上述配置中的Select(container => container.Model)是EF可解析的表达式,结合ExampleModel到ExampleModelDto的映射,AutoMapper会生成完整的服务器端投影SQL,只查询Something和Info等必要字段。
  3. 配置验证通过:该配置可以正常通过AssertConfigurationIsValid()验证,无映射错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 12:54:27