.NET Core Class 到 运行 方法每 15 分钟一次,使用 Hangfire 和依赖注入

.NET Core Class to run method every 15 minutes with Hangfire and Dependency Injection

我有我的 DbContext (IApplicationDbContext) 和另一个服务(API 调用)可通过依赖注入获得。

我需要每 15 分钟 运行 一个 Hangfire Recurrent Job 来联系几个 API 并获取数据,然后将其放入数据库。我想要一个包含作业方法的 class,但作业需要访问 DbContext 和服务。

我的服务注册为单例,我的 DbContext 注册为作用域服务。

谁能告诉我如何创建一个 class,其中包含一种方法,即每 15 分钟由 Hangfire 执行一次 运行 以及如何启动此作业?

我尝试创建一个名为 JobContext 的 class 接口 IJobContext,并通过 JobContext 中的构造函数注入 DbContext 和 ApiService,然后通过 AddSingleton 注册它,但它没有用,因为生命周期of 比 DbContext (Scoped) 更短。

我需要的:

  1. Class 包含 method/job
  2. class 需要通过 DI 的 DbContext 和 ApiService
  3. 运行 这个 class 在启动时,以便作业在 Hangfire 中注册并每 15 分钟执行一次

像这样:

public class JobContext : IJobContext
{
    public IApplicationDbContext ApplicationDbContext { get; set; }
    public IApiService ApiService { get; set; }

    public JobContext(IApplicationDbContext applicationDbContext, IApiService apiService)
    {
        ApplicationDbContext = applicationDbContext;
        ApiService = apiService;

        InitJobs();
    }

    public void InitJobs()
    {
        RecurringJob.AddOrUpdate(() => Execute(), Cron.Minutely);
    }

    public void Execute()
    {
        // This is my job... Do some Api requests and save to the Db
        Console.WriteLine("123");
    }
}

然后我在 Startup.cs#ConfigureServices 中尝试了(但失败了):

services.AddSingleton<IJobContext, JobContext>();

这是我得到的异常:

System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: ##.##.##.IJobContext Lifetime: Singleton ImplementationType: ##.##.##.JobContext': Cannot consume scoped service '##.##.##.IApplicationDbContext' from singleton'##.##.##.IJobContext'.)

非常感谢您的帮助!

您需要在 class 中创建 DbContext 的新实例。您不希望您的 DbContext 成为单身人士。

只需将一个作用域服务工厂注入您的 class。您可以使用此方法创建新范围并实例化范围内的服务。

public class JobContext : IJobContext
{
    public IServiceScopeFactory ServiceScopeFactory { get; set; }
    public IApiService ApiService { get; set; }

    public JobContext(IServiceScopeFactory serviceScopeFactory, IApiService apiService)
    {
        ServiceScopeFactory = serviceScopeFactory;
        ApiService = apiService;

        InitJobs();
    }

    public void InitJobs()
    {
        RecurringJob.AddOrUpdate(() => Execute(), Cron.Minutely);
    }

    public void Execute()
    {
        using var scope = ServiceScopeFactory.CreateScope();
        using var dbContext = scope.ServiceProvider.GetService<IApplicationDbContext>();
        
        // use your dbContext
        // This is my job... Do some Api requests and save to the Db
        Console.WriteLine("123");
    }
}