我正在使用 .NET Core 7 和 AutoMapper 12,我正在尝试创建从实体框架查询到 DTO 列表的映射。由于我需要 DTO 列表,因此我使用
AutoMapper中的
.ProjectTo()
函数
var configuration = new MapperConfiguration(cfg =>
{
cfg.CreateProjection<MachineSchedule, MachineScheduleDataDto>()
.ForMember(m => m.ShiftsDto, opts => opts.MapFrom(m => AddShiftCondition(m.Shifts, shiftType.Value))) // HERE
.ForMember(m => m.ScheduledStopsDto, opts => opts.MapFrom(m => m.ScheduledStops))
.ForMember(m => m.MachineOperationsDto, opts => opts.MapFrom(m => m.MachineOperations));
cfg.CreateProjection<MachineOperation, MachineOperationDto>()
.ForMember(m => m.EggQuantitiesDto, opts => opts.MapFrom(m => m.EggQuantities));
cfg.CreateProjection<EggQuantity, EggQuantityDto>();
cfg.CreateProjection<Shift, ShiftDto>();
cfg.CreateProjection<ScheduledStop, ScheduledStopDto>();
});
var queryMapper = configuration.CreateMapper();
var diffDays = GetWeekdaysBetweenDates(startDate, endDate);
var test = queryMapper.ProjectTo<MachineScheduleDataDto>(_typedContext?
.AsNoTracking()
.Include(m => m.Shifts)
.Include(m => m.ScheduledStops)
.Include(m => m.MachineOperations)!
.ThenInclude(m => m.EggQuantities)
.OrderBy(m => m.MachineScheduleId));
如您所见,我有方法AddShiftCondition:
private static IEnumerable<Shift>? AddShiftCondition(ICollection<Shift>? shifts, EShiftType? shiftType)
{
if (shifts != null && !shifts.Any())
return null;
if (shiftType.HasValue)
return shifts!.Where(s => s.Type == shiftType.Value);
return shifts;
}
我不知道为什么,但如果我使用
.ProjectTo()
,则不会调用AddShiftCondition,但如果我使用.Map()
,则一切正常:
var configuration = new MapperConfiguration(cfg =>
{
cfg.CreateMap<MachineSchedule, MachineScheduleDataDto>()
.ForMember(m => m.ShiftsDto, opts => opts.MapFrom(m => AddShiftCondition(m.Shifts, shiftType.Value)))
.ForMember(m => m.ScheduledStopsDto, opts => opts.MapFrom(m => m.ScheduledStops))
.ForMember(m => m.MachineOperationsDto, opts => opts.MapFrom(m => m.MachineOperations));
cfg.CreateMap<MachineOperation, MachineOperationDto>()
.ForMember(m => m.EggQuantitiesDto, opts => opts.MapFrom(m => m.EggQuantities));
cfg.CreateMap<EggQuantity, EggQuantityDto>();
cfg.CreateMap<Shift, ShiftDto>();
cfg.CreateMap<ScheduledStop, ScheduledStopDto>();
});
var queryMapper = configuration.CreateMapper();
var diffDays = GetWeekdaysBetweenDates(startDate, endDate);
var test = queryMapper.Map<MachineScheduleDataDto>(_typedContext?
.AsNoTracking()
.Include(m => m.Shifts)
.Include(m => m.ScheduledStops)
.Include(m => m.MachineOperations)!
.ThenInclude(m => m.EggQuantities)
.FirstOrDefault());
为什么会这样?
最简单的方法就是废弃该方法并编写表达式:
cfg.CreateProjection<MachineSchedule, MachineScheduleDataDto>()
.ForMember(m => m.ShiftsDto,
opts => opts.MapFrom(m => m.Shifts.Where(s => s.Type == shiftType.Value))) // add empty collection handling if needed, though I would keep it simple
ProjectTo
与IQueryable
配合使用,对于ORM(如EF Core),它将导致将LINQ查询转换为实际的SQL查询,并且对于某些任意方法来说这是不可能的(一般情况下)。
了解更多: