【问题标题】:What is an correct way to inject db context to Hangfire Recurring job?将数据库上下文注入 Hangfire Recurring 作业的正确方法是什么?
【发布时间】:2018-11-28 08:42:03
【问题描述】:

我正在使用 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");
        }
    }
}

【问题讨论】:

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


【解决方案1】:

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

假设您将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);

【讨论】:

    【解决方案2】:

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

    Create Container class

    将容器添加到 Hangfire:

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

    同时更改配置类中的作业注册:

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

    【讨论】:

      猜你喜欢
      • 2020-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多