Dapper的QueryMultiple方法可一次性执行含多个SELECT的SQL并按序获取多个结果集,返回GridReader对象,需严格按SQL中SELECT顺序调用Read()等方法读取,支持ReadSingle、Skip等进阶操作。
Dapper 的 QueryMultiple 方法用于执行一条 SQL 语句(通常是存储过程或含多个 SELECT 的批处理),并一次性获取多个结果集,比多次调用 Query 更高效、更节省数据库连接资源。
调用 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+ 支持)来“跳过”,避免潜在异常除了 Read,GridReader 还提供常用快捷方法:
ReadSingle() :读取单值结果(如 SELECT COUNT(*))ReadFirstOrDefault() :读第一个对象,无数据时返回 default(T)
Skip()(Dapper ≥ 2.0):跳过当前结果集,适合忽略中间某个结果IsConsumed 属性可检查是否所有结果集已被读完基本上就这些。QueryMultiple 不复杂但容易忽略顺序和生命周期管理,用对了能显著简化多结果集场景的代码。