如何在AutoMapper中向ProjectTo添加自定义方法?

问题描述 投票:0回答:1

我正在使用 .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());

为什么会这样?

.net entity-framework-core automapper mapper projectto
1个回答
0
投票

最简单的方法就是废弃该方法并编写表达式:

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查询,并且对于某些任意方法来说这是不可能的(一般情况下)。

了解更多:

© www.soinside.com 2019 - 2024. All rights reserved.