如何用Mapster将JOIN查询结果映射到含嵌套集合的DTO
解决视图扁平化数据集到嵌套DTO的映射问题
EF Core处理Include集合的底层逻辑
EF Core执行带Include的查询时,会先生成返回扁平化结果的SQL(和你视图的结构一致),之后在内存中通过以下步骤处理:
- 临时追踪主实体的ID(即使
AsNoTracking也会做临时的去重追踪) - 将结果集中重复的主实体合并,只保留一个实例
- 将对应行的子实体逐个添加到主实体的集合属性中
- 返回去重后的主实体列表,每个主实体包含完整的子实体集合
实现映射的两种方式
方式1:手动分组后再映射
先将视图返回的扁平化数据按主实体ID分组,构造出嵌套结构后再用Mapster映射到DTO,逻辑直观易调试。
首先建议重命名视图对应的实体类(避免和原SomeRecord冲突):
public sealed class SomeRecordView { public Guid Id { get; set; } public string Name { get; set; } public Guid SomeSubRecordId { get; set; } public string SomeSubRecordName { get; set; } }
然后执行查询、分组并映射:
// 从视图获取扁平化数据 var flatData = await _dbContext.Set<SomeRecordView>().ToListAsync(); // 按主实体ID分组,构建嵌套结构 var nestedData = flatData .GroupBy(r => new { r.Id, r.Name }) .Select(g => new { g.Key.Id, g.Key.Name, ListOfSomeSubRecords = g.Select(s => new SomeSubRecordResponse { Id = s.SomeSubRecordId, Name = s.SomeSubRecordName }) }); // 映射到目标DTO var responses = nestedData.Adapt<IEnumerable<SomeRecordResponse>>();
方式2:配置Mapster自动处理分组
通过配置Mapster的映射规则,让它自动完成扁平化数据到嵌套DTO的转换,减少手动分组的代码。
配置映射规则
// 配置从扁平化集合到嵌套DTO集合的映射 TypeAdapterConfig<IEnumerable<SomeRecordView>, IEnumerable<SomeRecordResponse>>.NewConfig() // 按主实体ID分组 .GroupUsing(src => src.GroupBy(r => r.Id)) // 映射主实体属性 .Map(dest => dest.Id, src => src.Key) .Map(dest => dest.Name, src => src.First().Name) // 映射子实体集合 .Map(dest => dest.ListOfSomeSubRecords, src => src.Select(s => new SomeSubRecordResponse { Id = s.SomeSubRecordId, Name = s.SomeSubRecordName }));
使用映射
var flatData = await _dbContext.Set<SomeRecordView>().ToListAsync(); var responses = flatData.Adapt<IEnumerable<SomeRecordResponse>>();
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

