Entity Framwork、SignalR、および Hangfire ジョブを使用する ASP.NET MVC プロジェクトがあります。
私のメイン (ルート) コンテナーは次のように定義されています。
builder.RegisterType<DbContext>().InstancePerLifetimeScope(); // EF Db Context
builder.RegisterType<ChatService>().As<IChatService>().SingleInstance(); // classic "service", has dependency on DbContext
builder.RegisterType<ChatHub>().ExternallyOwned(); // SignalR hub
builder.RegisterType<UpdateStatusesJob>().InstancePerDependency(); // Hangfire job
builder.RegisterType<HomeController>().InstancePerRequest(); // ASP.NET MVC controller
IContainer container = builder.Build();
MVC の場合、Autofac.MVC5 nuget パッケージを使用しています。依存関係リゾルバー:
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
SignalR の場合、Autofac.SignalR nuget パッケージを使用しています。依存関係リゾルバー:
GlobalHost.DependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container);
私の signalR ハブは次のようにインスタンス化されます ( http://autofac.readthedocs.org/en/latest/integration/signalr.html#managing-dependency-lifetimes ):
private ILifetimeScope _hubScope;
protected IChatService ChatService;
public ChatHub(ILifetimeScope scope) {
_hubScope = scope.BeginLifetimeScope(); // scope
ChatService = _hubScope.Resolve<IChatService>(); // this service is used in hub methods
}
protected override void Dispose(bool disposing)
{
// Dipose the hub lifetime scope when the hub is disposed.
if (disposing && _hubScope != null)
{
_hubScope.Dispose();
}
base.Dispose(disposing);
}
Hangfire の場合、Hangfire.Autofac パッケージを使用しています。
config.UseActivator(new AutofacJobActivator(container));
ジョブは次のようにインスタンス化されます。
private readonly ILifetimeScope _jobScope;
protected IChatService ChatService;
protected BaseJob(ILifetimeScope scope)
{
_jobScope = scope.BeginLifetimeScope();
ChatService = _jobScope.Resolve<IChatService>();
}
public void Dispose()
{
_jobScope.Dispose();
}
質問/問題: ハブとジョブで常に DbContext の同じインスタンスを取得します。すべてのハブ インスタンスが同じ ChatService を取得するようにしたいのですが、DbContext (ChatService の依存関係) は常に新しいインスタンスになります。また、Hangfire ジョブも同じように動作するはずです。
これを行うことができますか、それとも何か不足していますか?
更新 1:
考えた(そして寝た)後、私には2つの選択肢があると思います。「リクエストごとのセッション」(「ハブごとのセッション」、「ジョブごとのセッション」) を維持したいと考えています。
オプション1:
すべてのサービスが InstancePerLifetimeScope を持つように変更します。サービスのインスタンス化は高価ではありません。ある種の状態を維持するサービスの場合、SingleInstance でセッション (DbContext) に依存しない別の「ストレージ」(クラス) を作成します。これは、ハブやジョブでも機能すると思います。
オプション 2:
@Ric .Net によって提案されたある種のファクトリを作成します。このようなもの:
public class DbFactory: IDbFactory
{
public MyDbContext GetDb()
{
if (HttpContext.Current != null)
{
var db = HttpContext.Current.Items["db"] as MyDbContext;
if (db == null)
{
db = new MyDbContext();
HttpContext.Current.Items["db"] = db;
}
return db;
}
// What to do for jobs and hubs?
return new MyDbContext();
}
}
protected void Application_EndRequest(object sender, EventArgs e)
{
var db = HttpContext.Current.Items["db"] as MyDbContext;
if (db != null)
{
db.Dispose();
}
}
これはMVCで機能すると思いますが、ハブ(すべてのハブ呼び出しはハブの新しいインスタンスです)とジョブ(ジョブのすべての実行はジョブクラスの新しいインスタンスです)で機能させるにはどうすればよいかわかりません.
私は選択肢 1 に傾いています。どう思いますか?
どうもありがとう!