我有一个简单的Web API控制器:
public class CarsController : ApiController
{
public SqlConnection Db { get; set; }
public CarsController()
{
Db = new SqlConnection("XXX");
}
public async Task<IEnumerable<Car>> GetAll()
{
//Fetch cars from DB...
}
protected override void Dispose(bool disposing)
{
if (disposing)
Db.Dispose();
base.Dispose(disposing);
}
}
我将 dispose 代码放在 Dipose() 覆盖中,因为我想写一次。
我可以确定在任何情况下都会调用释放代码吗?(例外情况示例)。
我能否确定控制器将在号召性用语已完成,释放资源以应对即将推出调用。
- 如果没有,是否有更强大/正确的方法来做到这一点?
通过使用Dispose()
,您正在等待 GC 清理控制器。在 async Task
方法中使用 Using
语句,对象将立即被释放。无论是否异常,sqlConnection 对象都将被释放。您应该在async Task
中实例化SqlConnection
而不是构造函数,以有效地使用Using
。
也许你应该考虑使用依赖注入容器,以便控制 IDbConnection 实例化。特别是,查看生命周期管理器和 HierarchicalLifetimeManager。
这样,您就可以摆脱以每个请求的方式手动管理对象处置。
一个良好的开端
我认为您想使用此处概述的方法:在 Web API 请求结束时释放资源。
Web API 框架提供了方法 HttpRequestMessage.RegisterForDispose,允许您注册要在请求结束时释放的任何和所有引用。所以你的代码看起来像这样:
public class CarsController : ApiController
{
public SqlConnection Db { get; set; }
public CarsController()
{
Db = new SqlConnection("XXX");
Db.Open();
Request.RegisterForDispose(Db);
}
public async Task<IEnumerable<Car>> GetAll()
{
//Fetch cars from DB...
}
}
在我的项目中,我正在为所有控制器创建一个基类,在其中初始化数据库连接并注册它们以进行处置。因此,我不仅不会为我的操作编写任何 SqlConnection 样板,也不会为任何控制器编写。