使用QueryMultiple查询多结果集时如何自动生成带指定键名的字典存储
核心前提
数据库原生返回的多结果集本身不携带自定义名称标识,Dapper 的 GridReader 没有内置能力直接获取存储过程中查询的表/变量名,因此无法完全不做任何配置就自动生成 Orders、OrderDetails 这类键名,以下是两个可落地的实现方案:
方案1:无需修改存储过程(推荐)
调用时传入和结果集顺序一致的键名列表即可,实现最简单、性能无损耗,适配通用场景:
public async Task<Dictionary<string, IEnumerable<dynamic>>> QueryMultipleWithNamedResultsAsync( string procedureName, object param, IEnumerable<string> resultSetNames, IDbConnection connection) { var resultDict = new Dictionary<string, IEnumerable<dynamic>>(); var keyQueue = new Queue<string>(resultSetNames); using (var multi = await connection.QueryMultipleAsync(procedureName, param, commandType: CommandType.StoredProcedure)) { while (!multi.IsConsumed && keyQueue.Count > 0) { var currentKey = keyQueue.Dequeue(); var currentResult = multi.Read().ToList(); resultDict.Add(currentKey, currentResult); } } return resultDict; }
你的场景调用时传入 new[] {"Orders", "OrderDetails"} 即可得到符合要求的字典结构。
方案2:无需传入键名(需要修改存储过程)
如果希望通用方法完全不用传入键名,可以调整存储过程在每个数据结果集前返回一行名称标识,代码中交替读取名称和数据即可:
- 修改后的存储过程示例:
-- 每个数据结果集前先返回对应键名 SELECT 'Orders' AS ResultSetName; SELECT * FROM @Orders; SELECT 'OrderDetails' AS ResultSetName; SELECT * FROM @OrderDetails;
- C# 读取代码:
using (var multi = await connection.QueryMultipleAsync(procedureName, param, commandType: CommandType.StoredProcedure)) { var resultDict = new Dictionary<string, IEnumerable<dynamic>>(); while (!multi.IsConsumed) { // 读取结果集名称 var nameRow = multi.Read().FirstOrDefault(); if (nameRow == null) break; var resultName = nameRow.ResultSetName as string; // 读取对应数据 var data = multi.Read().ToList(); resultDict.Add(resultName, data); } return resultDict; }
注意事项
- 方案1需要确保传入的键名顺序和存储过程返回结果集的顺序完全匹配,否则会出现键值对应错误
- 两个方案都使用非泛型的
Read()方法读取 dynamic 类型结果,完全符合你的场景要求
内容的提问来源于stack exchange,提问作者Ivan-Mark Debono
相关产品推荐
相关产品推荐

