首页 > 解决方案 > .NET Core 类使用 Hangfire 和依赖注入每 15 分钟运行一次方法

问题描述

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

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

我的服务注册为单例,我的 DbContext 注册为范围服务。

有人可以告诉我如何创建一个包含一个由 Hangfire 每 15 分钟运行一次的方法的类,以及如何启动这项工作?

我尝试使用接口 IJobContext 创建一个名为 JobContext 的类,并通过 JobContext 中的构造函数注入 DbContext 和 ApiService,然后通过 AddSingleton 注册它,但它不起作用,因为 DbContext (Scoped) 的生命周期更短.

我需要的:

  1. 包含方法/作业的类
  2. 该类需要通过 DI 的 DbContext 和 ApiService
  3. 在 Startup 运行这个类,以便 Job 在 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'.)

非常感谢你的帮助!

标签: .net.net-coreschedulerjobshangfire

解决方案


您需要DbContext在您的班级中创建一个新的实例。你不希望你DbContext成为单身人士。

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

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");
    }
}

推荐阅读