Dapper是.NET生态中常用的轻量级ORM框架,其查询方法如Query、QueryAsync等都包含一个名为buffered的参数,这个参数用来控制查询结果的加载策略,直接影响查询的内存占用和执行效率。
buffered参数的基本定义
buffered是Dapper查询方法的一个布尔类型参数,默认值为true。它决定了Dapper是将查询结果一次性全部加载到内存中,还是采用流式的方式边读取边返回数据。
以同步查询方法Query为例,它的方法签名如下:
public static IEnumerable<T> Query<T>(
this IDbConnection cnn,
string sql,
object param = null,
IDbTransaction transaction = null,
bool buffered = true,
int? commandTimeout = null,
CommandType? commandType = null
)
可以看到buffered参数位于第四个位置,默认开启缓冲模式。
缓冲查询与非缓冲查询的核心区别
1. 内存占用差异
缓冲模式(buffered = true)下,Dapper会先将所有查询结果从数据库读取出来,存储在一个列表集合中,再把这个集合返回给调用方。这意味着整个结果集都会驻留在内存里,如果查询结果数据量很大,会占用大量内存,甚至引发内存溢出。
非缓冲模式(buffered = false)下,Dapper会返回一个迭代器,每次只从数据库读取一条或者一小批数据返回,不会把所有结果一次性加载到内存。整个查询过程中内存占用始终保持较低水平,适合处理大结果集。
2. 执行时机差异
缓冲模式下,调用查询方法后,Dapper会立即执行SQL语句,等待所有结果都加载完成后再返回。也就是说方法返回时,整个查询过程已经全部完成。
非缓冲模式下,调用查询方法后,Dapper只是返回了一个迭代器,SQL语句并没有立即完全执行,只有当开发者遍历这个迭代器的时候,才会逐批从数据库读取数据。如果遍历到一半停止,剩余的查询结果不会被加载。
3. 连接占用差异
缓冲模式下,所有结果加载完成后,数据库连接就可以被释放回连接池,连接占用时间相对较短。
非缓冲模式下,因为需要边遍历边读取数据,数据库连接会一直保持占用状态,直到迭代器遍历完成或者迭代器被释放。如果遍历过程耗时很长,会导致数据库连接长时间被占用,可能影响连接池的其他请求。
两种模式的使用示例
缓冲模式示例
默认情况下就是缓冲模式,适合小结果集查询:
using Dapper;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
public List<User> GetAllUsers(string connStr)
{
using (var conn = new SqlConnection(connStr))
{
// buffered默认是true,这里显式写出来方便理解
var users = conn.Query<User>("SELECT Id, Name, Age FROM Users", buffered: true).ToList();
return users;
}
}
非缓冲模式示例
处理大结果集时使用非缓冲模式,避免内存溢出:
using Dapper;
using System.Collections.Generic;
using System.Data.SqlClient;
public void ProcessLargeUserData(string connStr)
{
using (var conn = new SqlConnection(connStr))
{
// 开启非缓冲模式
var users = conn.Query<User>("SELECT Id, Name, Age FROM Large_Users_Table", buffered: false);
foreach (var user in users)
{
// 逐条处理数据,不会一次性加载所有数据到内存
Console.WriteLine($"处理用户:{user.Name}");
}
}
}
两种模式的适用场景
| 模式类型 | 适用场景 | 不适用场景 |
|---|---|---|
| 缓冲模式 | 查询结果数据量小,需要多次遍历结果集,需要快速拿到全部数据做后续处理 | 查询结果数据量极大,内存资源有限,只需要遍历一次结果 |
| 非缓冲模式 | 查询结果数据量极大,只需要遍历一次结果,内存资源有限 | 需要多次遍历结果集,需要快速拿到全部结果,连接池资源紧张 |
使用注意事项
- 非缓冲模式下,遍历迭代器的时候不要关闭数据库连接,否则会抛出异常。Dapper会在迭代器遍历完成后自动释放连接。
- 非缓冲模式下如果中途退出遍历,记得手动释放迭代器,避免数据库连接长时间占用。可以将迭代器放在using块中:
using (var users = conn.Query<User>(sql, buffered: false)) { ... } - 异步查询方法
QueryAsync同样支持buffered参数,使用逻辑和同步方法一致。
选择缓冲还是非缓冲模式,核心是根据查询结果的数据量和后续处理需求判断,小结果集优先用缓冲模式,大结果集优先用非缓冲模式。
Dapperbuffered参数查询缓冲非缓冲查询ORM修改时间:2026-07-07 20:09:34