Hi, i’m trying to use hangfire in our multi-tenant application, which has 2 databases, but sharing the same application code.
My goal is, depending on the URL (tenant1 ot tenant2), i need to create the job in the correct database. Tenant1 client goes to tenant1 DB, Tenant2 client goes to Tenant2 DB.
But it seems that after i have setup the connection string for the first time, i can’t change it for the subsequent time.
For example, this code :
Line2 BackgroundJob.Enqueue(JOB1) --> queue inserted to tenant1DB
Line4 BackgroundJob.Enqueue(JOB2) --> queue inserted to tenant2DB instead of tenant1DB, which is wrong
Is there a way to change the DB Connection string to be used properly?
Don’t use static methods like
BackgroundJob.Enqueue(). Create a new instance of
BackgroundJobClient every time, passing it a corresponding instance of
SqlServerStorage as argument.
If you use MVC and IoC, you may configure separate Areas, each having its own
IBackgroundJobClient services configured, so you can seamlessly inject them.
You may even turn these services into Scoped, so they’re resolved for each request. For .NET Core, it would be something like:
// Needed for JobStorage factory to work
var httpContext = x.GetRequiredService<IHttpContextAccessor>().HttpContext;
if (httpContext == null)
// If we don't have HttpContext present, then it must be UseHangfireServer/Dashboard()
// was called without the JobStorage parameter specified, so it tries to resolve it from IoC.
throw new InvalidOperationException("Server/dashboard must be started with JobStorage specified");
// inspect httpContext.User or httpContext.Request to determine the connection string
return new SqlServerStorage(GetConnectionString(httpContext));
// Services depending on JobStorage must be changed to Scoped too:
services.AddScoped<IBackgroundJobClient>(x => new BackgroundJobClient(
services.AddScoped<IRecurringJobManager>(x => new RecurringJobManager(
// Proceed with Hangfire setup
// Don't call UseSqlServerStorage() here
this is spot on! this is what i was looking for, to instantiate the BackgroundJobClient in every request, and use it instead the static BackgroundJob.Enqueue().
I don’t use .NET Core, i’m using servicestack for the app service. So for now i’m just gonna try the traditional way using Property in the service class and return the BackgroundJobClient with the connectionstring depending on the request.
But, the samples you gave me is very fancy, will do some R n D on that! Thank you!
I have used this for my multi-tenant project, mostly similar scenario. i have used RecurringJobManager instance in the middle ware and dynamically change sqlserverstorage as below
recurringJobManager.AddOrUpdate(tenant.Name, Job.FromExpression(() => Console.WriteLine("Great")), Cron.MinuteInterval(1));
but, another problem, that jobs record only in default tenant, it is not using another tenant to save its own jobs info