Dapper的QueryMultiple方法可一次性执行含多个SELECT的SQL并按序获取多个结果集,返回GridReader对象,需严格按SQL中SELECT顺序调用Read()等方法读取,支持ReadSingle、Skip等进阶操作。

Dapper 的 QueryMultiple 方法用于执行一条 SQL 语句(通常是存储过程或含多个 SELECT 的批处理),并一次性获取多个结果集,比多次调用 Query 更高效、更节省数据库连接资源。
基本用法:用 QueryMultiple 获取多个结果集
调用 QueryMultiple 后返回一个 SqlMapper.GridReader 对象,它支持按顺序读取每个结果集,每次调用 Read 就消耗一个结果集。
示例:查询用户列表 + 订单总数 + 最新3个订单
string sql = @"
SELECT * FROM Users WHERE Status = @status;
SELECT COUNT(*) FROM Orders WHERE UserId IN (SELECT Id FROM Users WHERE Status = @status);
SELECT TOP 3 * FROM Orders ORDER BY CreatedTime DESC;";
using var conn = new SqlConnection(connStr);
var multi = conn.QueryMultiple(sql, new { status = "Active" });
var users = multi.Read().ToList(); // 第一个结果集 → User 列表
var orderCount = multi.ReadSingle(); // 第二个结果集 → 单个 int 值
var recentOrders = multi.Read().ToList(); // 第三个结果集 → Order 列表
常见场景:配合存储过程使用
SQL Server 存储过程中用多个 SELECT 返回不同结构的数据时,QueryMultiple 是最佳选择。
- 确保每个
SELECT的列名和类型与目标 .NET 类型匹配(Dapper 按列名映射) - 避免在存储过程中使用
SET NOCOUNT ON—— 它会干扰 Dapper 解析结果集(除非你明确知道影响并做了适配) - 如果某结果集为空,
Read仍会返回空集合(如() IEnumerable),不会报错
注意点:顺序必须严格匹配,不能跳过或乱序
GridReader 是“游标式”读取,结果集按 SQL 中 SELECT 出现的顺序依次消费,且不可回退、不可重复读。
- 调用
Read一次,就向前推进一个结果集;跳过某个结果集会导致后续读取错位() - 不要对同一个
GridReader多次调用Read读同一结果集(第二次会返回空)() - 如果只想读前两个结果集,第三个不关心,也建议显式调用
multi.Read或multi.Skip()(Dapper v2+ 支持)来“跳过”,避免潜在异常
进阶技巧:泛型 ReadSingle / ReadFirstOrDefault / Skip
除了 Read,GridReader 还提供常用快捷方法:
-
ReadSingle:读取单值结果(如() SELECT COUNT(*)) -
ReadFirstOrDefault:读第一个对象,无数据时返回() default(T) -
Skip()(Dapper ≥ 2.0):跳过当前结果集,适合忽略中间某个结果 -
IsConsumed属性可检查是否所有结果集已被读完
基本上就这些。QueryMultiple 不复杂但容易忽略顺序和生命周期管理,用对了能显著简化多结果集场景的代码。










