You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Instead of having as separate TenantMiddleware, I get the TenantId from the HttpRequest by overriding the OnCreateAsync method in the DefaultHttpRequestInterceptor.
In the Program.cs only the TenantDbContext is registered with DbContext.Resolver (default), this creates a problem as with DbContext.Resolver a new resolver scope is created for the DbContext.
Therefore the ITenantProvider with request scope is not accessable anymore when adding a new TenantDbContext.
How do I fix this?
HttpRequestInterceptor.cs
public override async ValueTask OnCreateAsync(HttpContext context, IRequestExecutor requestExecutor, IQueryRequestBuilder requestBuilder, CancellationToken cancellationToken)
{
await base.OnCreateAsync(context, requestExecutor, requestBuilder, cancellationToken);
var dbContext = context.RequestServices.GetService<CentralDbContext>();
var tenantProvider = context.RequestServices.GetService<ITenantProvider>();
if (context.Request.Headers.TryGetValue("TenantId", out var headerValue) && int.TryParse(headerValue.ToString(), out var tenantId))
{
var tenant = await dbContext.Tenants.FirstOrDefaultAsync(e => e.Id == tenantId);
if (tenant != null)
{
tenantProvider.SetTenant(tenant);
return;
}
}
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<ITenantProvider, TenantProvider>();
// register the db contexts
builder.Services.AddDbContext<CentralDbContext>(options =>
{
options.UseMySql(_connectionString, ServerVersion.AutoDetect(connectionString));
});
builder.Services.AddDbContext<TenantDbContext>((serviceProvider, options) =>
{
var tenantProvider = serviceProvider.GetService<ITenantProvider>();
var tenant = tenantProvider?.GetTenant();
if (tenant is null)
throw new TenantNotSetException();
// set the db context to the tenant connection string
options.UseMySql(tenant.ConnectionString, ServerVersion.AutoDetect(tenant.ConnectionString));
});
builder.Services
.AddGraphQLServer()
.AddHttpRequestInterceptor<HttpRequestInterceptor>()
.AddTypes()
.RegisterDbContext<TenantDbContext>();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.MapGraphQL();
app.Run();
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hi,
I'm trying to implement multi-tenancy (Database per tenant) using Hotchocolate and Entity Framework Core based on the following blogpost:
https://youssefsellami.com/implementing-multi-tenancy-with-entityframework-core/
Instead of having as separate TenantMiddleware, I get the TenantId from the HttpRequest by overriding the OnCreateAsync method in the DefaultHttpRequestInterceptor.
In the Program.cs only the TenantDbContext is registered with DbContext.Resolver (default), this creates a problem as with DbContext.Resolver a new resolver scope is created for the DbContext.
Therefore the ITenantProvider with request scope is not accessable anymore when adding a new TenantDbContext.
How do I fix this?
HttpRequestInterceptor.cs
Program.cs
Beta Was this translation helpful? Give feedback.
All reactions