Automapper嵌套Select时EF Core不执行JOIN的问题求助
解决方案
你遇到的核心问题是:mapper.Map<T>()是内存操作,EF无法将其转换为SQL,导致既不会生成关联JOIN,还会因上下文命令冲突抛出异常;而ProjectTo<T>()虽能正确生成SQL,但目标Dto缺少分组用的DayOfWeek字段。下面是两种简洁且高效的解决方式:
方案一:先投影匿名类,内存映射后分组
先通过EF的Select生成包含DayOfWeek和所有Dto所需字段的匿名类(EF会自动生成必要JOIN并仅查询所需字段),再在内存中用AutoMapper映射为ScheduleEntryDto并分组:
// 第一步:从数据库查询所需的原始数据(含DayOfWeek和Dto字段) var rawScheduleData = await db.ScheduleEntries .Where(se => se.ClassId == studentsClassId) .OrderBy(se => se.LessonNumber) .Select(se => new { se.DayOfWeek, se.Id, se.LessonNumber, HostTeacher = se.EntryStub.TeacherFullname, Location = se.EntryStub.Location, SchoolClass = $"{se.Class.ClassNumber} {se.Class.ClassLetter}", SubjectName = se.EntryStub.Subject.Name // 补充ScheduleEntryDto需要的其他字段 }) .ToArrayAsync(); // 第二步:映射为Dto并分组 var entries = rawScheduleData .GroupBy(item => item.DayOfWeek) .ToDictionary( group => group.Key, group => group.Select(item => mapper.Map<ScheduleEntryDto>(item)).ToArray() );
方案二:用中间类配合ProjectTo投影
创建一个包含DayOfWeek和ScheduleEntryDto的中间类,通过AutoMapper的ProjectTo实现数据库端投影,再分组:
1. 定义中间类
public class ScheduleEntryWithDay { public DayOfWeek DayOfWeek { get; set; } public ScheduleEntryDto Entry { get; set; } }
2. 配置AutoMapper映射
确保已配置ScheduleEntry到ScheduleEntryDto的映射,再添加中间类的映射:
// 假设已存在ScheduleEntry到ScheduleEntryDto的映射 CreateMap<ScheduleEntry, ScheduleEntryWithDay>() .ForMember(dest => dest.DayOfWeek, opt => opt.MapFrom(src => src.DayOfWeek)) .ForMember(dest => dest.Entry, opt => opt.MapFrom(src => src));
3. 执行查询和分组
var entries = (await db.ScheduleEntries .Where(se => se.ClassId == studentsClassId) .OrderBy(se => se.LessonNumber) .ProjectTo<ScheduleEntryWithDay>(mapper.ConfigurationProvider) .ToArrayAsync()) .GroupBy(item => item.DayOfWeek) .ToDictionary( group => group.Key, group => group.Select(item => item.Entry).ToArray() );
为什么原代码会异常?
mapper.Map<ScheduleEntryDto>(se)是内存操作,EF无法将其转换为SQL,因此会尝试先加载ScheduleEntry的基础数据(不包含关联表,因为没显式JOIN),再在内存中映射。- 映射时访问
se.EntryStub等导航属性会触发延迟加载,此时数据库查询仍在进行中(ToArrayAsync()未完成),上下文同时处理两个命令,导致抛出'A Command Is Already In Progress'异常。
内容的提问来源于stack exchange,提问作者lkc
相关产品推荐
相关产品推荐

