Позвольте переписать то, что у вас есть на данный момент SelectMany
+ Select
, используя свойство навигации Consultant
:
var consultants = employees
.SelectMany(e => e.CommissionDetailConsultants)
.Select(com => new ConsultantGridViewModel
{
ConsultantName = com.Consultant.Name,
PayRate = com.Consultant.PayRateRegular,
LoadedRated = com.Consultant.PayRateLoadedRegular,
GM = com.Consultant.GMOutput,
BillRate = com.Project.BillRateRegular,
ProjectDescription = com.Project.Description,
ProjectStartDate = com.Project.StartDate,
ProjectEndDate = com.Project.EndDate,
CustomerName = com.Project.Customer.Name,
SalesPersonName = com.SalesPerson.Name,
CommissionPercent = com.CommissionPercent,
CommissionLevel = com.Level
});
Теперь видно, что CommissionDetail
содержит все необходимые данные,поэтому, хотя вы не можете избежать SelectMany
, вы можете заменить Select
, создав отображение от CommissionDetail
до ConsultantGridViewModel
и использовать что-то вроде этого:
var consultants = Mapper.Map<List<ConsultantGridViewModel>>(
employees.SelectMany(e => e.CommissionDetailConsultants));
или даже лучше, проектнепосредственно к DTO:
var consultants = await _dbContext.Employee
.Where(e => e.EmployeeType == "Contractor")
.SelectMany(e => e.CommissionDetailConsultants)
.ProjectTo<ConsultantGridViewModel>()
.ToListAsync();
Теперь отображение.
AutoMapper автоматически сопоставит элементы, такие как CommisionPercent
.Кроме того, функция Сглаживание автоматически обрабатывает сопоставления, такие как Project.EndDate
-> ProjectEndDate
, Consultant.Name
-> ConsultantName
и т. Д.
Так что, как обычно, в AutoMapper вы должны указать вручнуюотображение свойств, которые не попадают в предыдущие категории.Минимальная конфигурация в этом случае будет выглядеть примерно так:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<CommissionDetail, ConsultantGridViewModel>()
.ForMember(dst => dst.PayRate, opt => opt.MapFrom(src => src.Consultant.PayRateRegular))
.ForMember(dst => dst.LoadedRated, opt => opt.MapFrom(src => src.Consultant.PayRateLoadedRegular))
.ForMember(dst => dst.GM, opt => opt.MapFrom(src => src.Consultant.GMOutput))
.ForMember(dst => dst.BillRate, opt => opt.MapFrom(src => src.Project.BillRateRegular))
.ForMember(dst => dst.CustomerName, opt => opt.MapFrom(src => src.Project.Customer.Name))
.ForMember(dst => dst.CommissionLevel, opt => opt.MapFrom(src => src.Level));
});
PS Вы даже можете избежать SelectMany
, основав свои запросы непосредственно на CommissionDetail
сущности, например
var consultants = await _dbContext.Set<CommissionDetail>()
.Where(c => c.Consultant.EmployeeType == "Contractor")
.ProjectTo<ConsultantGridViewModel>()
.ToListAsync();
Обратите внимание, что при прямом проецировании нет необходимости в AsNoTracking
или Include
/ ThenInclude
.