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

Automapper使用带条件的自定义Resolver调用ProjectTo时报映射异常如何解决

问题解决方案

错误根因

  • ProjectTo方法会将AutoMapper映射逻辑转换为EF Core可解析的表达式树,最终生成SQL执行。你使用的自定义Resolver包含C#运行时逻辑(字符串截取、配置读取等),无法被转换为SQL语句,因此触发表达式构建失败异常。

可选解决方案

方案1:保留投影查询,移除自定义Resolver

将Resolver的逻辑改写为EF可解析的表达式,直接写在映射配置中:

// 映射配置调整
CreateMap<AppUser, MemberDto>()
    .ForMember(d => d.Image, o => o.MapFrom(src => 
        src.Photos.Any(x => x.IsMain)
        ? EF.Functions.Like(src.Photos.First(x => x.IsMain).Url, "http%")
            ? src.Photos.First(x => x.IsMain).Url
            : "你的固定ApiUrl前缀" + src.Photos.First(x => x.IsMain).Url
        : null
    ));

查询代码简化,无需传入额外参数:

public async Task<PagedList<MemberDto>> GetMembersAsync(UserParams userParams)
{
    var query = _context.Users.Include(p => p.Photos).AsQueryable();
    var mappedEntity = query.ProjectTo<MemberDto>(_mapper.ConfigurationProvider);
    return await PagedList<MemberDto>.CreateAsync(mappedEntity, 
            userParams.PageNumber, userParams.PageSize);
}

注意:该方案要求ApiUrl前缀使用常量,不能从配置文件动态读取,否则仍然无法转成SQL。

方案2:保留自定义Resolver,改为内存映射

放弃SQL层面的投影,先查询分页后的AppUser实体,再在内存中做DTO映射,Resolver的运行时逻辑可正常执行:

public async Task<PagedList<MemberDto>> GetMembersAsync(UserParams userParams)
{
    // 先对实体做分页查询
    var userQuery = _context.Users.Include(p => p.Photos).AsQueryable();
    var pagedUsers = await PagedList<AppUser>.CreateAsync(userQuery, 
            userParams.PageNumber, userParams.PageSize);
    
    // 内存映射为DTO,自定义Resolver正常生效
    var memberDtos = _mapper.Map<List<MemberDto>>(pagedUsers);
    
    // 组装分页结果返回
    return new PagedList<MemberDto>(memberDtos, pagedUsers.TotalCount, 
            userParams.PageNumber, userParams.PageSize);
}

内容的提问来源于stack exchange,提问作者Sami-L

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 06:27:00