将数据库上下文注入到Hangfire重复作业中的正确方法是什么?

时间:2018-11-28 08:42:04

标签: c# asp.net-core .net-core hangfire

我正在使用HangFire定期向后台用户发送电子邮件。

我正在从数据库中获取电子邮件地址,但不确定是否要将数据库上下文“注入”到负责正确发送电子邮件的服务中

这正常工作,有更好的方法吗?

public void Configure(IApplicationBuilder app, IHostingEnvironment env, Context context)
{
    (...)

    app.UseHangfireDashboard();
    app.UseHangfireServer(new BackgroundJobServerOptions
    {
        HeartbeatInterval = new System.TimeSpan(0, 0, 5),
        ServerCheckInterval = new System.TimeSpan(0, 0, 5),
        SchedulePollingInterval = new System.TimeSpan(0, 0, 5)
    });

    RecurringJob.AddOrUpdate(() => new MessageService(context).Send(), Cron.Daily);

    (...)
    app.UseMvc();
}

public class MessageService
{
    private Context ctx;

    public MessageService(Context c)
    {
        ctx = c;
    }

    public void Send()
    {
        var emails = ctx.Users.Select(x => x.Email).ToList();

        foreach (var email in emails)
        {
            sendEmail(email, "sample body");
        }
    }
}

3 个答案:

答案 0 :(得分:1)

答案 1 :(得分:0)

对于您的问题,绝对需要使用DI(StructureMap等)。请重构您的配置文件,并从配置类中解耦“上下文”类依赖项。还介绍了一个容器类来映射DI类(自动或手动)。

Create Container class

将容器添加到Hangfire:

GlobalConfiguration.Configuration.UseStructureMapActivator(Bootstrapper.Bootstrap());

还可以在配置类中更改作业注册:

RecurringJob.AddOrUpdate<MessageService>(x => x.Send(), Cron.Daily);

答案 2 :(得分:0)

我只是看了类似的问题,却找不到一个地方的信息,所以在这里发布我的解决方案。

假设您将Context配置为服务,即

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    ....
    services.AddDbContext<Context>(options => { ... });
    ....
}

这使IServiceProvider能够解决Context依赖性。

接下来,我们需要更新MessageService类,以使其不再永久保存Context,而仅将其实例化以执行任务。

public class MessageService
{
    IServiceProvider _serviceProvider;
    public MessageService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public void Send()
    {
        using (IServiceScope scope = _serviceProvider.CreateScope())
        using (Context ctx = scope.ServiceProvider.GetRequiredService<Context>())
        {
            var emails = ctx.Users.Select(x => x.Email).ToList();

            foreach (var email in emails)
            {
                sendEmail(email, "sample body");
            }
        }
    }
}

最后,我们要求 Hangfire 为我们实例化MessageService,它也将为我们解决IServiceProvider的依赖性:

RecurringJob.AddOrUpdate<MessageService>(x => x.Send(), Cron.Daily);