I'm using HangFire to send emails to users in the background, regularly.
I'm obtaining email addresses from database, but I'm not sure whether I'm "injecting" database context to service that's responsible for sending emails correctly
This works correctly, is there a better way to do it?
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");
}
}
}
I just looked to the similar question and did not find the information in one place, so posting my solution here.
Assume you have your Context
configured as a service, i.e.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
....
services.AddDbContext<Context>(options => { ... });
....
}
This makes the IServiceProvider
capable to resolve the Context
dependency.
Next, we need to update the MessageService
class in order to not hold the Context
forever but instantiate it only to perform the task.
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");
}
}
}
}
And finally we ask Hangfire to instantiate the MessageService
for us, it will also kindly resolve the IServiceProvider
dependency for us:
RecurringJob.AddOrUpdate<MessageService>(x => x.Send(), Cron.Daily);