问题描述
我通过依赖注入获得了DbContext(IApplicationDbContext)和另一个服务(可以进行API调用)。
我需要每15分钟运行一次Hangfire经常性作业,以联系多个API并获取数据,然后将其放入数据库中。我想拥有一个包含该作业方法的类,但是该作业需要访问DbContext和Service。
我的服务已注册为Singleton,我的DbContext已注册为范围服务。
有人可以告诉我如何创建一个包含每15分钟由Hangfire运行的方法的类以及如何启动此作业吗?
我试图用接口IJobContext创建一个名为JobContext的类,并通过JobContext中的构造函数注入DbContext和ApiService,然后通过AddSingleton进行注册,但是它没有用,因为DbContext的生命周期较短(范围)。
我需要什么:
类似这样的东西:
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'.)
非常感谢您的帮助!
解决方法
您需要在课程中创建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");
}
}