在Asp.NET核心中触发Quartz作业时处理上下文

时间:2017-05-31 09:18:03

标签: c# asp.net-core

我正在尝试从.NET核心中的Web API控制器构建一个Quartz作业触发器。 我已经成功使用 Startup 类中的简单计划创建了一个触发器:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider services)
        {
            loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseCors("CorsPolicy");

            app.UseApplicationInsightsRequestTelemetry();
            app.UseApplicationInsightsExceptionTelemetry();

            app.UseMvc();

            ProcessTracksScheduler.Start(services);          
        }

这是启动方法:

 public static class ProcessTracksScheduler
    {
        public static void Start(IServiceProvider provider)
        {
            try
            {
                ISchedulerFactory schedFact = new StdSchedulerFactory();
                IScheduler sched = schedFact.GetScheduler();
                sched.Start();

                IJobDetail job = JobBuilder.Create<ProcessTracksJob>()
                    .WithIdentity("ProcessTracks", "Group1")
                    .Build();

                job.JobDataMap["tracksService"] = provider.GetService(typeof(ITracksService));
                job.JobDataMap["cloudService"] = provider.GetService(typeof(ICloudService));
                job.JobDataMap["broadcastService"] = provider.GetService(typeof(IBroadcastService));
                job.JobDataMap["categoriesService"] = provider.GetService(typeof(ICategoriesService));

                ITrigger trigger = TriggerBuilder.Create()
                    .WithSimpleSchedule(x => x
                        .RepeatForever()
                        .WithInterval(TimeSpan.FromDays(1)))
                    .StartNow()
                    .Build();

                sched.ScheduleJob(job, trigger);

            }
            catch (ArgumentException e)
            {
                // Log the error
            }
        }
   }

工作:

public async void Execute(IJobExecutionContext context)
{
    var tracksService = context.MergedJobDataMap["tracksService"] as ITracksService;
    var cloudService = context.MergedJobDataMap["cloudService"] as ICloudService;
    var broadcastService = context.MergedJobDataMap["broadcastService"] as IBroadcastService;
    var categoryService = context.MergedJobDataMap["categoriesService"] as ICategoriesService;

    if (tracksService == null || cloudService == null || broadcastService == null || categoryService == null)
        return;

    var broadcasts = broadcastService.GetAll();
    // Some more work to do.
}

所以这个按预期工作,我很满意!但是这里的问题是当我尝试为我的Web API控制器只创建一次作业的触发器时:

[Route("Proccess")]
[HttpPost]
public async Task<IActionResult> ProccessTracks()
{
    ProcessTracksScheduler.StartOnce(serviceProvider);
    return Ok("Job scheduled");
}

StartOnce 方法,与Start:

基本相同
public static void StartOnce(IServiceProvider provider)
{
    try
    {
        ISchedulerFactory schedFact = new StdSchedulerFactory();
        IScheduler sched = schedFact.GetScheduler();
        sched.Start();

        IJobDetail job = JobBuilder.Create<ProcessTracksJob>()
            .WithIdentity("ProcessTracksOnce", "Group1")
            .Build();

        job.JobDataMap["tracksService"] = provider.GetService(typeof(ITracksService));
        job.JobDataMap["cloudService"] = provider.GetService(typeof(ICloudService));
        job.JobDataMap["broadcastService"] = provider.GetService(typeof(IBroadcastService));
        job.JobDataMap["categoriesService"] = provider.GetService(typeof(ICategoriesService));

        ITrigger trigger = TriggerBuilder.Create()
            .StartNow()
            .Build();

        sched.ScheduleJob(job, trigger);

    }
    catch (ArgumentException e)
    {
        // Log the error
    }
}

但是当我的工作被执行时,行var broadcasts = broadcastService.GetAll();会抛出一个异常,说我的 DbContext 已被处理..

DbContext通过DI传递给ASP.Net-Core的控制器/服务:

// In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(this.Configuration.GetConnectionString("MyConnString")));
    services.AddTransient<IBroadcastService, BroadcastsService>();
    // Add the others services.        
}

我尝试了很多东西,但是找不到解决这个问题的方法。

1 个答案:

答案 0 :(得分:0)

您是否曾尝试在构造函数中的ProcessTracksJob类中要求服务?我没有问题就这样使用它。

使用JobDataMap插入尝试如下:

public class ProcessTracksJob :IJob 
{
   private readonly ITracksService _tracksService;

   public ProcessTracksJob(ITracksService tracksService, etc.) 
   {
     _tracksService = tracksService;
     ...
   }

   /// the execute method using the private fields in this class

}