Search code examples
c#.net-corequartz-schedulerjobs

How to inject a service to a Job and setup IOC container configuration?


I set up a Job in which I injected a service from servicecollection. The problem is that this job (Execute method) could not be run although before injecting any services, it was working properly.

I think the problem stems from Dependency Injection Lifetime because when I change all lifetimes to Singleton the job is fired. For the reason that DbContext should be Transient I have to solve it in another way.

Statup.cs:

public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            services.AddDbContext<EFDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Cnn")).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking), ServiceLifetime.Transient);
            services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

            services.AddTransient<CheckTransactionConfirmJob>();
            services.AddTransient<CheckPaymentConfirmationScheduler>();

            services.AddTransient<IPaymentRepository, EfPlanRepository>();
            
        }

PaymentService.cs:

        private async Task RunPaymentCheckerJob(Payment payment, Guid userId,
            CheckPaymentConfirmationScheduler scheduler)
        {
            IJobDetail job = JobBuilder.Create<CheckTransactionConfirmJob>()
                .WithIdentity(Guid.NewGuid().ToString(), "CheckConfirmationJob")
                .UsingJobData("paymentId", payment.Id)
                .UsingJobData("userId", userId)
                .Build();

            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(Guid.NewGuid().ToString(), "CheckConfirmationGroup")
                .WithSimpleSchedule(x => x
                    .WithIntervalInSeconds(20)
                    .WithRepeatCount(12))
                .ForJob(job)
                .Build();
            await scheduler.GetScheduler().ScheduleJob(job, trigger);
        }

CheckTransactionConfirmJob.cs

public class CheckTransactionConfirmJob : IJob
    {
        private readonly IPaymentRepository _paymentRepository;
        private readonly IServiceProvider _provider;

        public CheckTransactionConfirmJob(IPaymentRepository paymentRepository, IServiceProvider provider)
        {
            _paymentRepository = paymentRepository;
            _provider = provider;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                /// business code
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

        }

    }

Solution

  • Quartz comes with two built-in alternatives for job factory which can be configured via either calling UseMicrosoftDependencyInjectionJobFactory or UseMicrosoftDependencyInjectionScopedJobFactory (deprecated).

    For using Microsoft dependency UseMicrosoftDependencyInjectionJobFactory should be called in ConfigureServices method:

        services.AddQuartz(q =>
        {
            q.UseMicrosoftDependencyInjectionJobFactory();
        });