JobActivator in Hangfire doesnt instancelize DataContext for each run of RecurringJob

822 views Asked by At

I am using HangFire and EntityFramework for recurring job

public void Start(IContainer container)
{
  GlobalConfiguration.Configuration
   .UseColouredConsoleLogProvider(LogLevel.Debug)
   .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
   .UseSimpleAssemblyNameTypeSerializer()
   .UseActivator(new MyActivator(container))
   .UseRecommendedSerializerSettings();

   RecurringJob.AddOrUpdate<EveryMinute>((x) => x.ExecuteAsync(), Cron.Minutely);
}

Activator:

public class MyActivator : JobActivator
{
  private readonly IContainer _container;

  public MyActivator (IContainer container)
  {
    _container = container;
  }

  public override object ActivateJob(Type type)
  {
    return _container.Resolve(type);
  }
}

Then I had ctor initialization of Datacontext and RepositoryA

public EveryMinute(DataContext dataContext,RepositoryA repositoryA)
{
  _dataContext = dataContext;
  _repositoryA = repositoryA;
}

However when i retrieved data from DB in each minute like bellow i received wrong data(Item was updated outside of Hangfire job by other application).

public async Task ExecuteAsync()
{
  var dbItem = _dataContext.Items.Single(x => x.Id == 1);
  //dbItem.StateProperty property is old
}

It looks like item or DataContext is 'cached' from time of job creation(application start). Because when I used

public EveryMinute()
{
    _dataContext = new DataContext();
    _repositoryA = new RepositoryA(_dataContext);
}

It works fine.

Am I using activator wrong? Or how to specify that I need new instance DataContext for each call of dependency injection?

1

There are 1 answers

0
Pribina On BEST ANSWER

Jobs in Hangfire shares instance of activator.

Therefore I used Hangfire Autofac nuget - Hangfire.Autofac.

you can have specify for dependency to have instance per job

containerBuilder.RegisterType<DataContext>().InstancePerBackgroundJob();

and then in config

GlobalConfiguration.Configuration.UseAutofacActivator(containerBuilder.Build())