Hello,
We are attempting to use Hangfire for processing background jobs in an existing web application (code first EF).
This is messaged based and we have a number of Logics registered in a unity IOC container (we resolve based on the name of the message sent).
This appears to be working ok using a unity based Job Activator; however we are getting a performance issue when trying to create a new instance of our DBContext (we have a factory class DBContextFactory that does this and is an injected interface from Unity).
Once the background job starts and we it reaches the point where it calls for a new context from the above factory it takes ages (minutes) to create this where as in a usual synchronous context it is near instant.
My question is: are we missing anything? I’m not sure whether Lifetime managers come into play here?
Happy to clarify anything, thanks!
I do use Hangfire on a scenario like that, except the DBContextFactory, without any problems.
With Unity the DBContext lifetime should be the controlled by a HierarchicalLifetimeManager, so, your DBContext will be disposed with your Unity ChildContainer, that must be created per Scope .
On the latest versions of Hangfire you have the JobActivator and the JobActivatorScope. The BeginScope method of your JobActivator should create a JobActivatorScope that will “owns” an instance of your Unity Container, but, created with the IUnityContainer.CreateChildContainer().
Then, on your implementation of the JobActivatorScope, inside of the DisposeScope method you should dispose the child container owned by the Scope.
That way, your DbContext lifetime will be bound to the Scope of the job being executed.
However, A.F.A.I.K., even if your DbContext isn’t bound to the scope of the job and isn’t having his lifetime managed this way, it shouldn’t presents that performance issue creating the new context… you should investigate it in your factory as well.
“…to create this where as in a usual synchronous context it is near instant…” - Your background jobs are Asynchronous? if yes, maybe it’s worth to look into the Task’s context’s - ConfigureAwait(false) for the awaited ones, since you won’t need the calling context - and Job parameters (Very complex objects ??)