Asp.net Core Quartz 作业调用控制器方法,但上下文
Asp.net Core Quartz job calling controller method, but context
我有一个 aspnetcore 服务器(服务于 Blazor wasm 应用程序),它有一个 Quartz 计划作业 运行。当作业触发时,它会在我的服务器的一个控制器上调用一个方法。
如果我在我的控制器上正常调用此方法(例如通过网络 API 调用),它工作正常。
当我从 Quartz IJob 调用方法时,控制器中使用的 DbContext 似乎已被释放。
我试过以正常方式以及通过 IServiceProvider 将控制器注入到作业中,两者的结果相同。
控制器:
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
}
}
我的工作(IServiceProvider 尝试):
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();
}
}
}
我的工作(DI 尝试):
public class ReminderJob : IJob
{
private readonly NotificationController notificationController;
public ReminderJob(NotificationController notificationController)
{
this.notificationController = notificationController;
}
public async Task Execute(IJobExecutionContext jobcontext)
{
await notificationController.MyMethod();
}
}
我的Startup.cs(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")));
}
VS在尝试执行context.SaveChangesAsync()时没有抛出异常,但是,在它没有命中之后直接断点,但是当我在调试时检查上下文的细节时,它没有似乎填充正确。
如何在 IJob 中使用 Controller,并确保不丢弃 Controller 的依赖项?
How do I use the Controller from within the IJob
不要在作业中使用控制器。
Move/Extract/Refactor 将所需功能转化为服务抽象
//Service abstraction
public interface INotificationService {
Task MyMethod();
}
public class NotificationService : INotificationService {
private readonly ApplicationDbContext context;
public NotificationService(ApplicationDbContext context) {
this.context = context;
}
public async Task MyMethod() {
await context.SaveChangesAsync();
}
}
并让作业和控制器依赖于服务来调用所需的功能。
public class NotificationController : ControllerBase {
private readonly INotificationService service;
public NotificationController (INotificationService service ) {
this.service = service ;
}
public async Task<IActionResult> MyMethod() {
await service.MyMethod();
return Ok();
}
}
public class ReminderJob : IJob {
private readonly INotificationService service;
public ReminderJob(INotificationService service) {
this.service = service;
}
public Task Execute(IJobExecutionContext jobcontext) {
return service.MyMethod();
}
}
当然还有向 DI 容器注册所有必要的服务。
//...
services.AddScoped<INotificationService, NotificationService>();
//...
我有一个 aspnetcore 服务器(服务于 Blazor wasm 应用程序),它有一个 Quartz 计划作业 运行。当作业触发时,它会在我的服务器的一个控制器上调用一个方法。
如果我在我的控制器上正常调用此方法(例如通过网络 API 调用),它工作正常。
当我从 Quartz IJob 调用方法时,控制器中使用的 DbContext 似乎已被释放。 我试过以正常方式以及通过 IServiceProvider 将控制器注入到作业中,两者的结果相同。
控制器:
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
}
}
我的工作(IServiceProvider 尝试):
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();
}
}
}
我的工作(DI 尝试):
public class ReminderJob : IJob
{
private readonly NotificationController notificationController;
public ReminderJob(NotificationController notificationController)
{
this.notificationController = notificationController;
}
public async Task Execute(IJobExecutionContext jobcontext)
{
await notificationController.MyMethod();
}
}
我的Startup.cs(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")));
}
VS在尝试执行context.SaveChangesAsync()时没有抛出异常,但是,在它没有命中之后直接断点,但是当我在调试时检查上下文的细节时,它没有似乎填充正确。
如何在 IJob 中使用 Controller,并确保不丢弃 Controller 的依赖项?
How do I use the Controller from within the IJob
不要在作业中使用控制器。
Move/Extract/Refactor 将所需功能转化为服务抽象
//Service abstraction
public interface INotificationService {
Task MyMethod();
}
public class NotificationService : INotificationService {
private readonly ApplicationDbContext context;
public NotificationService(ApplicationDbContext context) {
this.context = context;
}
public async Task MyMethod() {
await context.SaveChangesAsync();
}
}
并让作业和控制器依赖于服务来调用所需的功能。
public class NotificationController : ControllerBase {
private readonly INotificationService service;
public NotificationController (INotificationService service ) {
this.service = service ;
}
public async Task<IActionResult> MyMethod() {
await service.MyMethod();
return Ok();
}
}
public class ReminderJob : IJob {
private readonly INotificationService service;
public ReminderJob(INotificationService service) {
this.service = service;
}
public Task Execute(IJobExecutionContext jobcontext) {
return service.MyMethod();
}
}
当然还有向 DI 容器注册所有必要的服务。
//...
services.AddScoped<INotificationService, NotificationService>();
//...