使用DTO的自动多对多映射程序



这是我第一次真正尝试使用Automapper,我很难使用DTO正确映射多对多关系。

以下是型号:

public class Camp
{
[Key]
public long Id { get; set; }
[Required]
[MaxLength( 150 )]
public string Name { get; set; }
[Required]
[MaxLength( 150 )]
public string Location { get; set; }       
[Required]
public DateTime StartDate { get; set; }
[NotMapped]
public int CampYear
{
get => StartDate.Year;
}    
public bool Archived { get; set; }    
public ICollection<Application> Applications { get; set; }    
public ICollection<CampStaffPosition> CampStaffPositions { get; set; }
}
public class StaffPosition
{
[Key]
public int Id { get; set; }
public string PositionName { get; set; }    
public ICollection<CampStaffPosition> CampStaffPositions { get; set; }
}
public class CampStaffPosition
{
public long CampId { get; set; }    
public Camp Camp { get; set; }    
public int StaffPositionId { get; set; }    
public StaffPosition StaffPosition { get; set; }    
public short PositionQuantity { get; set; } // Additional Info
}

我试图映射到的DTO:

public class CampDto
{
public long Id { get; set; }    
public string Name { get; set; }    
public string Location { get; set; }    
public DateTime StartDate { get; set; }    
public int CampYear { get; }    
public bool Archived { get; set; }    
public ICollection<ApplicationDto> Applications { get; set; }    
public ICollection<StaffPositionDto> Positions { get; set; } // Through CampStaffPositions
}
public class StaffPositionDto
{
public int Id { get; set; }    
public string Type { get; set; }    
public string PositionName { get; set; }    
public short PositionQuantity { get; set; } // From CampStaffPositions
}

在阅读了其他几篇SO帖子并试图效仿他们的例子后,我发现了不足。以下是几种不同的映射尝试:

CreateMap<Camp, CampDto>()
.ForMember( d => d.Positions, opt => opt.MapFrom( d => d.CampStaffPositions.Select( d => d.StaffPosition ).ToList() ) );
CreateMap<StaffPosition, CampDto>()
.ForMember( pr => pr.Positions, opt => opt.MapFrom( cp => cp.PositionName ) );
CreateMap<StaffPosition, StaffPositionDto>();
//CreateMap<StaffPosition, StaffPositionDto>()
//    .ForMember( cr => cr.PositionQuantity, opt => opt.MapFrom( c => c.CampStaffPositions ) );

这些是我最近收到的错误(包括评论行(:

Unable to create a map expression from StaffPosition.CampStaffPositions (System.Collections.Generic.ICollection`1[Server.Models.CampStaffPosition]) to StaffPositionDto.PositionQuantity (System.Int16) 
Mapping types: StaffPosition -> StaffPositionDto Server.Models.StaffPosition -> Shared.Dto.Core.StaffPositionDto 
Type Map configuration: StaffPosition -> StaffPositionDto Server.Models.StaffPosition -> Shared.Dto.Core.StaffPositionDto Destination Member: PositionQuantity

并且排除了注释行:

Expression of type 'System.Collections.Generic.List`1[Server.Models.StaffPosition]' cannot be used for parameter of type 'System.Linq.IQueryable`1[Server.Models.StaffPosition]' of method 'System.Linq.IQueryable`1[Shared.Dto.Core.StaffPositionDto] Select[StaffPosition,StaffPositionDto](System.Linq.IQueryable`1[Server.Models.StaffPosition], System.Linq.Expressions.Expression`1[System.Func`2[Server.Models.StaffPosition,Shared.Dto.Core.StaffPositionDto]])'

如何映射多对多以包含联接表中的附加属性,而不必在DTO中包含联接表?

您需要展平一个复杂的对象。子对象中有属性,您希望将其提升一个级别,同时仍然利用AutoMapper映射功能。有一种叫做IncludeMembers()的方法(参见文档(正是针对这种情况而存在的。它允许您为子类型重用现有映射中的配置,这样,当从CampStaffPosition映射到StaffPositionDto:时,PositionName将从充当第二个源的子对象StaffPosition中包含

config.CreateMap<Camp, CampDto>()
.ForMember(d => d.Positions, o => o.MapFrom(s => s.CampStaffPositions));
config.CreateMap<StaffPosition, StaffPositionDto>();
config.CreateMap<CampStaffPosition, StaffPositionDto>()
.IncludeMembers(p => p.StaffPosition);
config.CreateMap<Application, ApplicationDto>();

用法:

var result = mapper.Map<List<CampDto>>(campsFromDatabase);

或使用ProjectTo():

var result = await dbContext
.Set<Camp>()
.ProjectTo<CampDto>(mapper.ConfigurationProvider)
.ToListAsync();

最新更新