在定义了两个依赖于作用域服务 (ScopedDataAccess) 的作业(该服务是我的数据库上下文的包装器)之后,我很难将 Quartz 3.0.7 与 ASP.NET Core 2.2 一起使用:
services.AddScoped<IScopedDataAccess, ScopedDataAccess>();
services.AddDbContext<AggregatorContext>(opt => opt.UseSqlServer(configuration.GetConnectionString("Default")));
问题是两个作业接收相同的作用域服务实例(因此具有相同的数据库上下文),从而由于并行使用而导致上下文崩溃。
我的代码如下:
启动.cs
作业被定义为“范围”,我的期望是每个实例都在自己的“范围”中运行
private void ConfigureQuartz(IServiceCollection services, params Type[] jobs)
{
services.AddSingleton<IJobFactory, QuartzJobFactory>();
services.Add(jobs.Select(jobType => new ServiceDescriptor(jobType, jobType, ServiceLifetime.Scoped)));
services.AddSingleton(provider =>
{
var schedulerFactory = new StdSchedulerFactory();
var scheduler = schedulerFactory.GetScheduler().Result;
scheduler.JobFactory = provider.GetService<IJobFactory>();
scheduler.Start();
return scheduler;
});
}
protected void StartJobs(IApplicationBuilder app, IApplicationLifetime lifetime)
{
var scheduler = app.ApplicationServices.GetService<IScheduler>();
var configService = app.ApplicationServices.GetService<IConfigurationService>();
QuartzServicesUtilities.StartJob<ArticleXUserDataRefresherJob>(scheduler,
TimeSpan.FromSeconds(configService.ArticleXUserDataRefresherJobPeriod));
QuartzServicesUtilities.StartJob<LinkDataFetchJob>(scheduler,
TimeSpan.FromSeconds(configService.LinkDataJobPeriod));
lifetime.ApplicationStarted.Register(() => scheduler.Start());
lifetime.ApplicationStopping.Register(() => scheduler.Shutdown());
}
Quartz服务实用程序
public class QuartzServicesUtilities
{
public static void StartJob<TJob>(IScheduler scheduler, TimeSpan runInterval)
where TJob : IJob
{
var jobName = typeof(TJob).FullName;
var job = JobBuilder.Create<TJob>()
.WithIdentity(jobName)
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity($"{jobName}.trigger")
.StartNow()
.WithSimpleSchedule(scheduleBuilder =>
scheduleBuilder
.WithInterval(runInterval)
.RepeatForever())
.Build();
scheduler.ScheduleJob(job, trigger);
}
}
石英工作工厂
public class QuartzJobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
public QuartzJobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var jobDetail = bundle.JobDetail;
var job = (IJob)_serviceProvider.GetService(jobDetail.JobType);
return job;
}
public void ReturnJob(IJob job) { }
}
有没有办法使用 Quartz.NET 为不同的作业获取不同的作用域?