I have an aspnetcore server (serving a Blazor wasm app), which has a Quartz scheduled job running. When the job triggers, it is calling a method on one of my server's controllers.
If I call this method on my controller normally (e.g. via a web API call), it works fine.
When I call the method from the Quartz IJob, the DbContext used in the controller seems to be disposed. I've tried injecting the controller into the job in the normal way, and also via IServiceProvider, and both have the same result.
Controller:
public class NotificationController : ControllerBase
{
private readonly ApplicationDbContext context;
public NotificationService(ApplicationDbContext context)
{
this.context = context;
}
public async Task MyMethod()
{
await context.SaveChangesAsync(); //This is where it fails when Quartz calls it, seems context is not populated
}
}
My job (IServiceProvider attempt):
public class ReminderJob : IJob
{
private readonly IServiceProvider serviceProvider;
public ReminderJob(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public async Task Execute(IJobExecutionContext jobcontext)
{
using (var scope = serviceProvider.CreateScope())
{
await scope.ServiceProvider.GetRequiredService<NotificationController>().MyMethod();
}
}
}
My job (DI attempt):
public class ReminderJob : IJob
{
private readonly NotificationController notificationController;
public ReminderJob(NotificationController notificationController)
{
this.notificationController = notificationController;
}
public async Task Execute(IJobExecutionContext jobcontext)
{
await notificationController.MyMethod();
}
}
My Startup.cs (relevant lines in ConfigureServices):
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddControllersWithViews();
services.AddMvcCore().AddControllersAsServices();
services.AddRazorPages();
services.AddQuartz(q =>
{
q.UseMicrosoftDependencyInjectionScopedJobFactory(); //I also tried passing options.CreateScope to this method, but no difference
q.AddJobAndTrigger<ReminderJob>(configuration);
});
services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
}
No exception is thrown in VS when it attempts to do context.SaveChangesAsync(), however, a breakpoint directly after it is not hit, however when I check the details of context while debugging, it doesn't seem to be populated correctly.
How do I use the Controller from within the IJob, and ensure the Controller's dependencies are not disposed of?