17370845950

Dapper的IDbConnection怎么管理 Dapper连接的生命周期
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 poolsCurrent # pooled connections

事务中连接生命周期要对齐

当用 BeginTransaction() 时,连接必须处于 Open 状态,且事务对象的生命周期不能超过连接:

  • 事务必须在同一个连接上开启和提交/回滚
  • 推荐结构:外层 using 连接 → 中层 using 事务 → 内层 Dapper 方法传入 transaction 参数
  • 错误示范:连接在事务 Commit() 前就 Dispose() 了 → 抛出 InvalidOperationException

基本上就这些。不复杂但容易忽略——连错一次,可能拖垮整个服务的并发能力。