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

如何在Dapper中将查询结果映射到含集合属性的对象列表

高效映射SQL多行结果到ImageGallery属性的方法

下面提供几种比手动循环匹配更高效的实现方式:

1. 使用LINQ GroupBy分组聚合

利用LINQ的GroupBy一次性完成分组与属性映射,底层经过优化,代码简洁且性能优异:

// 假设从SQL查询获取的原始数据集合(包含PageId、所有PageEditDto字段及ImageUrl)
var rawRecords = FetchRawDataFromSql();

var pageDtos = rawRecords
    .GroupBy(record => record.PageId)
    .Select(group => new PageEditDto
    {
        PageId = group.Key,
        Header = group.First().Header,
        Content = group.First().Content,
        StartDate = group.First().StartDate,
        EndDate = group.First().EndDate,
        PageTypeId = group.First().PageTypeId,
        PublishPlaceId = group.First().PublishPlaceId,
        PublishPlacesList = group.First().PublishPlacesList,
        SubjectTypeId = group.First().SubjectTypeId,
        ApprovedBy = group.First().ApprovedBy,
        ApprovedAt = group.First().ApprovedAt,
        PageIconPath = group.First().PageIconPath,
        ReadQuantity = group.First().ReadQuantity,
        MainImage = group.First().MainImage,
        // 聚合同一PageId下的所有ImageUrl到列表
        ImageGallery = group.Select(r => r.ImageUrl)
                           .Where(url => !string.IsNullOrEmpty(url))
                           .ToList()
    })
    .ToList();

2. 借助ORM内置的一对多映射(以Dapper为例)

如果使用Dapper,可以通过其回调映射机制处理一对多关系,避免手动循环:

var pageLookup = new Dictionary<Guid, PageEditDto>();

await connection.QueryAsync<PageEditDto, string, PageEditDto>(
    @"SELECT p.*, ig.ImageUrl 
      FROM Pages p 
      LEFT JOIN ImageGallery ig ON p.PageId = ig.PageId",
    (page, imageUrl) =>
    {
        if (!pageLookup.TryGetValue(page.PageId, out var existingPage))
        {
            existingPage = page;
            existingPage.ImageGallery = new List<string>();
            pageLookup.Add(page.PageId, existingPage);
        }
        if (!string.IsNullOrEmpty(imageUrl))
        {
            existingPage.ImageGallery.Add(imageUrl);
        }
        return existingPage;
    },
    splitOn: "ImageUrl" // 指定拆分字段,区分主实体和关联图片地址
);

var pageDtos = pageLookup.Values.ToList();

3. 在SQL层面完成聚合(适合大数据量场景)

利用数据库的字符串聚合函数,先将同一PageId的图片地址聚合成单条记录,再在C#中拆分,减少传输数据量:

SQL示例(SQL Server)

SELECT 
    p.PageId,
    p.Header,
    p.Content,
    p.StartDate,
    p.EndDate,
    p.PageTypeId,
    p.PublishPlaceId,
    p.SubjectTypeId,
    p.ApprovedBy,
    p.ApprovedAt,
    p.PageIconPath,
    p.ReadQuantity,
    p.MainImage,
    -- 聚合图片地址为特殊分隔符的字符串
    STRING_AGG(ig.ImageUrl, '|') AS AggregatedImages
FROM Pages p
LEFT JOIN ImageGallery ig ON p.PageId = ig.PageId
GROUP BY p.PageId, p.Header, p.Content, p.StartDate, p.EndDate,
         p.PageTypeId, p.PublishPlaceId, p.SubjectTypeId, p.ApprovedBy,
         p.ApprovedAt, p.PageIconPath, p.ReadQuantity, p.MainImage

C#映射代码

var pageDtos = rawSqlResults.Select(r => new PageEditDto
{
    PageId = r.PageId,
    Header = r.Header,
    // 其他属性赋值...
    ImageGallery = string.IsNullOrEmpty(r.AggregatedImages)
        ? new List<string>()
        : r.AggregatedImages.Split('|').ToList()
}).ToList();

注意:如果图片地址可能包含分隔符,要选择业务中不会出现的特殊字符作为分隔符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:35:32