You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mapster将JOIN查询结果映射到含嵌套集合的DTO

解决视图扁平化数据集到嵌套DTO的映射问题

EF Core处理Include集合的底层逻辑

EF Core执行带Include的查询时,会先生成返回扁平化结果的SQL(和你视图的结构一致),之后在内存中通过以下步骤处理:

  1. 临时追踪主实体的ID(即使AsNoTracking也会做临时的去重追踪)
  2. 将结果集中重复的主实体合并,只保留一个实例
  3. 将对应行的子实体逐个添加到主实体的集合属性中
  4. 返回去重后的主实体列表,每个主实体包含完整的子实体集合

实现映射的两种方式

方式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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 19:03:20