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

在Dapper .NET API中实现Media对象多层嵌套映射的问题

Dapper多层嵌套对象映射方案(适配Media类结构变更)

类结构示例

先明确修改后的实体类结构(对应业务需求的变更):

public class Media
{
    public int MediaId { get; set; }
    public string Title { get; set; }
    // 原YoutubeID、VimeoID改为内部列表属性
    public List<VideoId> VideoIds { get; set; } = new List<VideoId>();
}

public class VideoId
{
    public string YoutubeId { get; set; }
    public string VimeoId { get; set; }
}

解决方案1:Multi-Mapping + 内存分组

利用Dapper的多对象映射能力获取扁平结果,再通过内存分组合并相同Media实例的嵌套列表:

// 关联查询SQL,确保返回Media主表+视频ID关联表的所有字段
var sql = @"
SELECT m.MediaId, m.Title, v.YoutubeId, v.VimeoId
FROM Media m
LEFT JOIN VideoIds v ON m.MediaId = v.MediaId";

var mediaList = connection.Query<Media, VideoId, Media>(
    sql,
    // 临时映射:将每行的VideoId加入当前Media的列表
    (media, videoId) =>
    {
        if (videoId != null)
            media.VideoIds.Add(videoId);
        return media;
    },
    // 指定拆分点:从YoutubeId字段开始,将结果映射到VideoId对象
    splitOn: "YoutubeId"
)
// 按MediaId分组,合并相同Media的VideoIds列表
.GroupBy(m => m.MediaId)
.Select(g =>
{
    var mergedMedia = g.First();
    mergedMedia.VideoIds = g.SelectMany(m => m.VideoIds).ToList();
    return mergedMedia;
})
.ToList();

解决方案2:手动构建嵌套结构(更灵活)

如果担心Dapper自动映射时重复创建Media实例,直接查询扁平数据后手动构建嵌套对象:

var flatResults = connection.Query<dynamic>(sql);
var mediaDict = new Dictionary<int, Media>();

foreach (var item in flatResults)
{
    int mediaId = item.MediaId;
    // 不存在则创建新的Media实例
    if (!mediaDict.TryGetValue(mediaId, out var media))
    {
        media = new Media
        {
            MediaId = mediaId,
            Title = item.Title,
            VideoIds = new List<VideoId>()
        };
        mediaDict.Add(mediaId, media);
    }
    // 仅当视频ID不为空时添加到列表
    if (!string.IsNullOrWhiteSpace(item.YoutubeId) || !string.IsNullOrWhiteSpace(item.VimeoId))
    {
        media.VideoIds.Add(new VideoId
        {
            YoutubeId = item.YoutubeId,
            VimeoId = item.VimeoId
        });
    }
}

// 最终得到嵌套结构的Media列表
var mediaList = mediaDict.Values.ToList();

关键注意点

  • 字段映射匹配:确保SQL返回的字段名与类属性名一致,不一致时用SQL别名(如SELECT youtube_id AS YoutubeId)或Dapper的[Column]特性标记。
  • 空列表初始化:在Media类中提前初始化VideoIds为空列表,避免JSON序列化时出现null值。
  • splitOn参数:使用Multi-Mapping时,splitOn必须指定嵌套对象的第一个字段,否则Dapper无法正确拆分映射。

内容的提问来源于stack exchange,提问作者Rajiv Ranjan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 20:44:58