Dapper 不管理 IDbConnection 生命周期,开发者必须用 using 确保及时释放;禁止长期持有连接、跨线程共享或手动频繁 Open/Close;事务需与连接生命周期对齐。

Dapper 本身不管理 IDbConnection 的生命周期,它完全依赖 ADO.NET 底层(如 SqlConnection)和开发者显式控制。关键不是“Dapper 怎么管”,而是“你必须自己管好”——否则极易出现连接泄漏、池耗尽、线程安全问题。
用 using 确保连接及时释放
这是最基础也最关键的实践。每次使用连接都应包裹在 using 块中,确保 Dispose() 被调用,连接归还到池里:
- 即使发生异常,
using也会触发Dispose(),避免连接卡死在打开状态 - 不要把
IDbConnection作为类字段长期持有,也不要在构造函数里直接Open() - 示例写法正确:
using var conn = new SqlConnection(connStr);
conn.Open();
var users = conn.Query("SELECT * FROM Users");
别跨线程共享同一个连接实例
IDbConnection(尤其是 SqlConnection)不是线程安全的:
- 一个连接对象只能被一个线程在某一时刻使用
- 多线程并发调用
Query()或Execute()到同一个连接实例,会抛出异常或导致未定义行为 - 正确做法:每个线程用自己的
using连接,或通过连接池自动分配新连接
配合连接池,别手动 Open/Close 多余次数
ADO.NET 连接池会复用物理连接,但前提是你的使用方式符合它的预期:
- 连接字符串必须完全一致(包括空格、大小写),否则视为不同池
- 频繁
new SqlConnection().Open().Close().Dispose()没问题——池会接管并复用 - 但若长期保持
Open()状态(比如放在静态字段里),池无法回收,最终触发“等待连接超时” - 检查池是否健康:观察性能计数器 SqlClient: Current # connection pools 和 Current # pooled connections
事务中连接生命周期要对齐
当用 BeginTransaction() 时,连接必须处于 Open 状态,且事务对象的生命周期不能超过连接:
- 事务必须在同一个连接上开启和提交/回滚
- 推荐结构:外层
using连接 → 中层using事务 → 内层 Dapper 方法传入transaction参数 - 错误示范:连接在事务
Commit()前就Dispose()了 → 抛出InvalidOperationException
基本上就这些。不复杂但容易忽略——连错一次,可能拖垮整个服务的并发能力。










