【问题标题】:Execute DB call within Scheduled Job在 Scheduled Job 中执行 DB 调用
【发布时间】:2017-12-18 12:26:04
【问题描述】:

我有一个在 ASP Core 2 下构建的项目,该项目利用 Quartz.NET 调度程序 3-beta1

我有以下想要执行的工作:

public class TestJob: IJob
{
    private readonly AppDbContext _dbContext;
    public TestJob(AppDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public Task Execute(IJobExecutionContext context)
    {
        Debug.WriteLine("Test check at " + DateTime.Now);

        var testRun = _dbContext.TestTable.Where(o => o.CheckNumber > 10).ToList();

        Debug.WriteLine(testRun.Count);

        return Task.CompletedTask;
    }
}

不幸的是,它永远无法正常工作,并且没有错误日志表明存在问题。

然而,当我删除所有内容并离开 Debug.WriteLine 时,它的工作原理如下例所示。

public class TestJob: IJob
    {
        public Task Execute(IJobExecutionContext context)
        {
            Debug.WriteLine("Test check at " + DateTime.Now);

            return Task.CompletedTask;
        }
    }

我怎样才能让我的工作来执行数据库调用?

编辑 1:创造就业机会

var schedulerFactory = new StdSchedulerFactory(properties);
            _scheduler = schedulerFactory.GetScheduler().Result;
            _scheduler.Start().Wait();

var testJob = JobBuilder.Create<TestJob>()
    .WithIdentity("TestJobIdentity")
    .Build();
var testTrigger = TriggerBuilder.Create()
    .WithIdentity("TestJobTrigger")
    .StartNow()
    .WithSimpleSchedule(x => x.WithIntervalInMinutes(1).RepeatForever())
    .Build();


if (CheckIfJobRegistered(testJob.Key).Result == false)
    _scheduler.ScheduleJob(testJob, testTrigger).Wait();

【问题讨论】:

  • 您是否使用任何工厂来创造就业机会?
  • 是的,我现在将我的代码用于创造就业机会
  • JobBuilder 不是工厂,它为作业创建定义。 Quartz 在执行前不久创建了该作业。但是 Quartz 不知道如何使用自定义构造函数来创建作业。您需要一个空的默认构造函数或自定义 JobFactory 来创建作业。
  • 不确定我明白你的意思。作业已创建,只是在我注入 dbcontext 时不执行
  • 但谁创造了这份工作?您在编辑中的 Job Creation 不会创建作业,它只是安排它。也许您的示例不完整,但我看不到您注入 dbcontext 或创建作业的任何内容。

标签: asp.net-core asp.net-core-2.0 quartz.net


【解决方案1】:

这里的主要问题是 Quartz 无法创建作业并吞下异常。

Documentation 声明:

当触发器触发时,它关联的 JobDetail(实例定义)被加载,并且它引用的作业类通过调度器上配置的 JobFactory 实例化。默认 JobFactory 仅使用 Activator.CreateInstance 调用作业类的默认构造函数,然后尝试调用类上与 JobDataMap 中的键名匹配的 setter 属性。您可能希望创建自己的 JobFactory 实现来完成诸如让应用程序的 IoC 或 DI 容器生成/初始化作业实例等事情。

Quartz 提供了IJobFactory 来实现这一点。它与依赖注入一起工作得非常好。 JobFactory 可以如下所示:

public class JobFactory : IJobFactory
{
    //TypeFactory is just the DI Container of your choice
    protected readonly TypeFactory Factory;

    public JobFactory(TypeFactory factory)
    {
        Factory = factory;
    }

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        try
        {
            return Factory.Create(bundle.JobDetail.JobType) as IJob;
        }
        catch (Exception e)
        {
            //Log the error and return null
            //every exception thrown will be swallowed by Quartz 
            return null;
        }
    }

    public void ReturnJob(IJob job)
    {
        //Don't forget to implement this,
        //or the memory will not released
        Factory.Release(job);
    }
}

然后只需向调度程序注册您的 JobFactory,一切都会正常工作:

_scheduler.JobFactory = new JobFactory(/*container of choice*/);

编辑:

另外你可以看看我以前的answers

【讨论】:

  • 谢谢,我会继续调查,到目前为止,我还无法使用那里的代码注入 dbcontext,所以仍然无法在 db 上执行查询。
  • 我使用标准的 Asp Core 依赖注入,它在 StartUp 应用中注册了我的所有服务。
  • @Aeseir 我的链接答案没有帮助?
  • 虽然它有助于形成理解,但我仍然无法注入我的 dbcontex 并因此进行查询。谷歌搜索我还没有看到一个答案告诉我如何在工作中注入实际的 DbContext。
  • @Aeseir 您确定它已在您的容器中注册吗?当您尝试从容器中解析作业/dbcontext 时会遇到什么异常?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
相关资源
最近更新 更多