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
相关产品推荐
相关产品推荐

