c# - 使用 DTO 的 Automapper 多对多
问题描述
这是我第一次真正尝试使用 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()
(请参阅文档),正是针对这种情况而存在的。它允许您在现有映射中为子类型重用配置,这样在从to映射时将包含在充当第二源PositionName
的子对象中:StaffPosition
CampStaffPosition
StaffPositionDto
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();
推荐阅读
- python - 如何使用 Pandas 获取数据透视表中行标题的行号?
- python-3.x - Python 无法执行 powershell 脚本
- html - 为什么我的 CSS 动画只有在开发工具中选择元素时才有效?
- matlab - 我可以在 for 循环中使用 GlobalSearch 来优化 Matlab 中的参数范围吗?
- python - Sklearn Predict_Proba: ValueError: 操作数不能与形状一起广播 (44,57) (4,)
- python - 检查一个列表中有多少元素包含在第二个列表中,包括重复项
- java - 如何使用 -XX:OnOutOfMemoryError= 在 OOM 执行脚本
- android - Android Firebase:Robo 脚本在位置权限对话框中失败
- java - 在 FXML 文件中定义属性时,Scene Builder 未打开
- kubernetes - 使用 Docker-Compose 和 Kubernetes 连接到 Mongo 的 NodeJ 的基础知识