You need to enable JavaScript to run this app. Automapper投影场景下如何实现EF Account到AccountDto的自定义映射逻辑
优惠活动
大模型
产品
解决方案
定价
更多

Automapper投影场景下如何实现EF Account到AccountDto的自定义映射逻辑

解决方案

因为 Linq to EF 投影要求映射逻辑必须能被转换为可解析的表达式树,自定义 ValueResolver 属于运行时逻辑无法被EF识别,你可以直接在 MapFrom 中编写内联的判断逻辑,或者将逻辑封装为可复用的表达式:

方案1:直接编写内联映射逻辑(最简单)

直接在映射配置里写判断逻辑,EF可以直接解析为SQL语句:

profile.CreateMap<Account, AccountDto>()
    .ForMember(dest => dest.PortfolioType, opt => opt.MapFrom(src =>
        src.PortfolioTypeAXref != null && src.PortfolioTypeAXref.PortfolioTypeAId.HasValue ? PortfolioType.A
        : src.PortfolioTypeBXref != null && src.PortfolioTypeBXref.PortfolioTypeBId.HasValue ? PortfolioType.B
        : src.PortfolioTypeCXref != null && src.PortfolioTypeCXref.PortfolioTypeCId.HasValue ? PortfolioType.C
        : src.PortfolioTypeDXref != null && src.PortfolioTypeDXref.PortfolioTypeDId.HasValue ? PortfolioType.D
        : PortfolioType.Unknown
    ))
    .ForMember(dest => dest.PortfolioId, opt => opt.MapFrom(src =>
        src.PortfolioTypeAXref != null && src.PortfolioTypeAXref.PortfolioTypeAId.HasValue ? src.PortfolioTypeAXref.PortfolioTypeAId
        : src.PortfolioTypeBXref != null && src.PortfolioTypeBXref.PortfolioTypeBId.HasValue ? src.PortfolioTypeBXref.PortfolioTypeBId
        : src.PortfolioTypeCXref != null && src.PortfolioTypeCXref.PortfolioTypeCId.HasValue ? src.PortfolioTypeCXref.PortfolioTypeCId
        : src.PortfolioTypeDXref != null && src.PortfolioTypeDXref.PortfolioTypeDId.HasValue ? src.PortfolioTypeDXref.PortfolioTypeDId
        : null
    ));

方案2:封装可复用的表达式(适合多场景复用逻辑)

如果你不想重复写判断逻辑,可以把判断逻辑封装为独立的表达式,再引入到映射配置中:

// 先定义可复用的判断表达式
public static readonly Expression<Func<Account, (PortfolioType Type, long? Id)>> PortfolioInfoExpr = src =>
    src.PortfolioTypeAXref != null && src.PortfolioTypeAXref.PortfolioTypeAId.HasValue 
        ? (PortfolioType.A, src.PortfolioTypeAXref.PortfolioTypeAId)
        : src.PortfolioTypeBXref != null && src.PortfolioTypeBXref.PortfolioTypeBId.HasValue 
            ? (PortfolioType.B, src.PortfolioTypeBXref.PortfolioTypeBId)
            : src.PortfolioTypeCXref != null && src.PortfolioTypeCXref.PortfolioTypeCId.HasValue 
                ? (PortfolioType.C, src.PortfolioTypeCXref.PortfolioTypeCId)
                : src.PortfolioTypeDXref != null && src.PortfolioTypeDXref.PortfolioTypeDId.HasValue 
                    ? (PortfolioType.D, src.PortfolioTypeDXref.PortfolioTypeDId)
                    : (PortfolioType.Unknown, null);

// 映射配置中引入表达式
profile.CreateMap<Account, AccountDto>()
    .ForMember(dest => dest.PortfolioType, opt => opt.MapFrom(PortfolioInfoExpr.Combine(x => x.Type)))
    .ForMember(dest => dest.PortfolioId, opt => opt.MapFrom(PortfolioInfoExpr.Combine(x => x.Id)));

注:上面用到的 Combine 是表达式树拼接的扩展方法,如果你不需要复用逻辑,直接用方案1即可。

验证

配置完成后直接用 ProjectTo<AccountDto>() 投影即可,EF会自动把上面的判断逻辑转换为SQL的CASE WHEN语句,不会触发客户端评估。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 19:36:03