EF Core 5实体ID从int改为Guid后出现LINQ表达式无法转换错误
问题根因
该报错是EF Core 5的查询转换器无法识别AutoMapper ProjectTo自动生成的表达式导致:你将主键改为Guid类型后,AutoMapper生成的子集合关联逻辑里带了object.Equals装箱调用、EF.Property显式访问语法,再加上你把过滤逻辑放在了投影之后,双重因素导致EF Core无法将整个LINQ语句转换为SQL。
解决方案(按优先级排序)
方案1:调整过滤顺序,提前过滤实体
将针对UserId的过滤移到ProjectTo执行之前,直接对UserProfile实体的Guid主键做过滤,EF Core可以正常转换这类主键比对逻辑:
var result = await _unitOfWork.Repository<Domain.Entities.UserProfile>() .Entities .AsNoTracking() .Where(x => x.Id == request.UserId) // 提前过滤实体主键 .Include(x => x.LanguageSkills) .ProjectTo<GeneralUserInfoModel>(_mapper.ConfigurationProvider) .FirstOrDefaultAsync(cancellationToken: cancellationToken);
方案2:显式配置AutoMapper映射规则
如果业务要求必须在投影后做过滤,可以在AutoMapper的配置中显式指定子集合的映射来源,避免AutoMapper自动生成嵌套子查询:
// GeneralUserInfoModel的映射配置 CreateMap<UserProfile, GeneralUserInfoModel>() .ForMember(dest => dest.LanguageSkills, opt => opt.MapFrom(src => src.LanguageSkills)); // LanguageSkills的映射保持正常配置即可 CreateMap<LanguageSkills, LanguageSkillsModel>();
方案3:拆分查询与映射步骤
单条数据查询场景下,可以直接先查实体再做映射,完全规避表达式转换问题,没有可感知的性能损失:
var userProfile = await _unitOfWork.Repository<Domain.Entities.UserProfile>() .Entities .AsNoTracking() .Include(x => x.LanguageSkills) .FirstOrDefaultAsync(x => x.Id == request.UserId, cancellationToken); var result = _mapper.Map<GeneralUserInfoModel>(userProfile);
内容的提问来源于stack exchange,提问作者Мстислав Павлов
相关产品推荐
相关产品推荐

