Asp.net Core Quartz作业调用控制器方法,但调用上下文



我有一个aspnetcore服务器(为Blazor wasm应用程序提供服务(,它运行着一个Quartz调度作业。当作业触发时,它正在我的服务器的一个控制器上调用一个方法。

如果我在我的控制器上正常调用这个方法(例如通过web 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在尝试执行上下文时不会引发异常。然而,SaveChangesAsync((是一个断点,直接在它没有被命中之后,但是当我在调试时检查上下文的详细信息时,它似乎没有被正确填充。

我如何在IJob中使用控制器,并确保控制器的依赖关系不会被处理?

如何在IJob 中使用控制器

请勿在作业中使用控制器。

将所需功能移动/提取/重构到服务抽象中

//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>();
//...

相关内容

  • 没有找到相关文章

最新更新