当我的ASP.NET MVC应用程序中存在持久HTTP连接(如SignalR集线器)时,我在管理具有作用于HttpContext的StructureMap的开放数据库连接的生命周期时遇到问题.
我的DI容器StructureMap将一个打开的IDbConnection注入到多个服务中.为确保关闭并正确处理这些数据库连接,我在EndRequest事件上调用ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects().
这对于MVC控制器非常有用,直到需要数据库连接的服务注入到SignalR集线器中,从而为每个客户端保持持久的HTTP连接,并最终使连接池饱和.
如果我将IDbConnection范围限定为单例,则每个应用程序只打开一个连接,并且池不会饱和,但如果连接被锁定或超时,则为a bad idea.
那么也许有一种方法可以自定义SignalR集线器的数据库连接范围?我尝试在每个Hub方法中解析服务实例,但这仍然在HttpContext范围内实例化数据库连接,并在调用客户端的集线器连接期间保持打开状态.
当存在持久的HTTP连接时,如何在HTTP范围的上下文中管理与StructureMap的数据库连接的生命周期?
示例代码
典型服务
public class MyService { private IDbConnection _con; public MyService(IDbConnection con) { _con = con; } public IEnumerable<string> GetStuff() { return _con.Select<string>("SELECT someString FROM SoMetable").ToList(); } }
典型的SignalR Hub
public class MyHub : Hub { private MyService _service; public MyHub(MyService service) { _service = service; // Oh Noes! This will open a database connection // for each Client because of HttpContext scope } public Task AddMessage() { var result = _service.GetStuff(); // ... } }
StructureMap配置
For<IDbConnection>() .HybridHttpOrThreadLocalScoped() .Use(() => BaseController.GetOpenConnection(MyConnectionString));
的Global.asax.cs
public class GlobalApplication : System.Web.HttpApplication { public GlobalApplication() { EndRequest += delegate { ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects(); }; } // ... }