如何在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
相关产品推荐
相关产品推荐

