I'm rewriting this entire question because I realize the cause, but still need a solution:
I have a recurring job in Hangfire that runs every minute and check the database, possibly updates some stuff, then exits.
I inject my dbcontext into the class containing the job method. I register this dbcontext to get injected using the following
builder.RegisterType<ApplicationDbContext>().As<ApplicationDbContext>().InstancePerLifetimeScope();
However, it seems that Hangfire does not create a seperate lifetime scope every time the job runs, because the constructor only gets called once, although the job method get's called every minute.
This causes issues for me. If the user updates some values in the database (dbcontext gets injected somewhere else, and used to update values), the context still being used Hangfire starts returning out-dated values that have already been changed.
To work around this problem, I've created a disposable JobContext class that has a ILifetimeScope that will be disposed when Hangfire completes the job. The real job is invoked by reflection.
There is a JobActivator that will inspect the action and create the LifetimeScope if necessary.
To assist with creating jobs, without using string parameters there is another class with some extensions.
So to queue up a job, e.g. with the following signature:
The code to create the job looks like
We have created a new pull request in the Hangfire.Autofac with the work around described by Dresel. Hopefully it gets merged in the main branch:
https://github.com/HangfireIO/Hangfire.Autofac/pull/4
Hangfire currently uses a shared Instance of
JobActivator
for every Worker, which are using the following method for resolving a dependency:It is planned to add a JobActivationContext to this method for Milestone 2.0.0.
For now, there is no way to say for which job a dependency gets resolved. The only way I can think of to workaround this issue would be to use the fact that jobs are running serial on different threads (I don't know AutoFac so I use Unity as an example).
You could create a
JobActivator
that can store separate scopes per thread:Use a
JobFilter
withIServerFilter
implementation to set this scope for every job (thread):And finally setup your DI:
A solution is supported out-of-the-box since hangfire.autofac 2.2.0.
In your situation, where your dependency is being registered per-lifetime-scope, you should be able to use non-tagged scopes when setting up hangfire.autofac. From the link:
Edit: With Autofac, .NET 4.5 and Hangfire >= 1.5.0, use the Hangfire.Autofac nuget package (github).
Working with .NET 4.0 (Autofac 3.5.2 and Hangfire 1.1.1), we set up Dresel's solution with Autofac. Only difference is in the JobActivator: