HttpContext
SignalRハブなどのASP.NETMVCアプリケーションに永続的なHTTP接続がある場合にスコープされた、StructureMapを使用したオープンデータベース接続の有効期間の管理に問題があります。
私のDIコンテナであるStructureMapは、IDbConnection
いくつかのサービスにオープンを注入します。これらのデータベース接続が閉じられ、適切に破棄されるようにするために、私ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects()
はEndRequest
イベントを呼び出します。
これは、データベース接続を必要とするサービスがSignalRハブに注入されるまで、MVCコントローラーに最適です。これにより、クライアントごとに永続的なHTTP接続が開いたままになり、最終的に接続プールが飽和状態になります。
シングルトンにスコープIDbConnection
を設定すると、アプリケーションごとに1つの接続のみが開かれ、プールが飽和状態になりませんが、接続がロックされたりタイムアウトになったりした場合に備えて、これはお勧めできません。
では、SignalRハブのデータベース接続の範囲をカスタマイズする方法はあるのでしょうか。各ハブメソッドでサービスインスタンスを解決しようとしましたが、これでも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ハブ
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();
};
}
// ...
}