如何正确使用UnitOfWork、Repository及Dispose?排查SQL连接耗尽问题
诊断UnitOfWork的Dispose()未正确调用导致SQL连接耗尽问题
兄弟,看你遇到的SQL连接耗尽问题,十有八九是UnitOfWorks的Dispose()没被正确执行,导致数据库连接一直被占用,没放回连接池。结合你给出的代码片段,咱先拆解问题,再给你靠谱的修正方案。
现有代码的核心问题
从你贴的UnitOfWorks代码片段来看,它大概率没有实现IDisposable接口——这是确保Dispose()能被自动调用的前提。你的KaprukaEntities应该是EF的DbContext,它内部持有数据库连接,如果UnitOfWorks的Dispose()没触发,DbContext的连接就不会被释放回连接池,日积月累直接把连接池耗干,最终导致SQL服务拒绝新连接。
确保Dispose()执行的修正方案
1. 让UnitOfWorks实现IDisposable接口
这是基础,必须先让类符合.NET的资源释放规范,同时实现安全的资源释放逻辑(防止重复释放、兜底终结器):
public class UnitOfWorks : IDisposable { private KaprukaEntities context; private bool disposed = false; // 标记是否已完成资源释放 // 你的现有代码:比如GenericRepository实例化、业务方法等 // private GenericRepository<SomeEntity> _someRepo; // public GenericRepository<SomeEntity> SomeRepo => _someRepo ??= new GenericRepository<SomeEntity>(context); // 公开的Dispose方法,供外部调用或using语句自动调用 public void Dispose() { Dispose(true); GC.SuppressFinalize(this); // 告诉GC无需再调用终结器,避免重复释放 } // 受保护的重载方法,区分托管/非托管资源释放 protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // 释放托管资源:这里重点是你的DbContext context?.Dispose(); } // 如果有非托管资源(比如文件句柄、原生API资源),在这里释放(你当前场景大概率没有) disposed = true; } } // 终结器:作为兜底,防止外部忘记调用Dispose时,GC回收前能释放资源 ~UnitOfWorks() { Dispose(false); } }
2. 用using语句包裹UnitOfWorks的实例
这是最稳妥的使用方式,using语句会自动在代码块结束时调用Dispose()——哪怕代码块内抛出异常也会执行,完全不用手动操心:
using (var unitOfWork = new UnitOfWorks()) { // 执行你的业务逻辑:比如调用仓储方法、提交更改 var data = unitOfWork.SomeRepository.GetById(123); data.Status = "Updated"; unitOfWork.SaveChanges(); // 假设你有提交DbContext更改的方法 } // 到这里,using块结束,unitOfWork的Dispose()已自动执行,连接被释放回池
3. 修复现有代码中未释放的实例
检查项目中所有手动实例化UnitOfWorks的地方,把这种错误写法:
// 错误:实例化后未释放,连接一直被占用 var unitOfWork = new UnitOfWorks(); unitOfWork.DoBusinessLogic();
改成两种正确写法之一:
- 要么用
using(推荐) - 要么用
try/finally手动调用Dispose():
var unitOfWork = new UnitOfWorks(); try { unitOfWork.DoBusinessLogic(); } finally { unitOfWork.Dispose(); // 无论是否异常,都确保释放 }
补充说明
DbContext的连接并不是在你执行查询时就立刻释放,而是会被DbContext持有到它被Dispose的时候。如果一直不Dispose,连接池里的可用连接会越来越少,直到耗尽——这就是你遇到SQL服务停止的根本原因。按照上面的方案修改后,连接会被及时释放回池,就不会再出现连接耗尽的问题了。
内容的提问来源于stack exchange,提问作者Saj
相关产品推荐
相关产品推荐

