Closed olegsAtQualtero closed 4 months ago
Duplicate of #3204
tl;dr that warning just means that you're instantiating more than some fix number of service providers, to help users catch the scenario where they're creating a service provider for each and every DbContext (which would be very bad). If you have a fixed number of tenants, and each tenant has a single NpgsqlDataSource (which, before https://github.com/npgsql/efcore.pg/issues/3086, causes a single EF service provider to be created), then you can safely suppress the warning and just proceed. Just make sure you're not creating a data source every single time you're instantiating a DbContext etc.
@NinoFloris turned my attention to this:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//resolved tenant connection string from SSM.
var connectionString = dbConfig.Connection.ConnectionString;
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
dataSourceBuilder.UseNodaTime();
var dataSource = dataSourceBuilder.Build(); // THIS IS BAD
optionsBuilder.UseNpgsql(dataSource);
}
Since OnConfiguring gets called for each DbContext instance, that means a data source gets built here for each and every context instance; this is a serious problem, as e.g. each data source represents a connection pool (so this effectively kills connection pooling).
You need to create the data source outside of OnConfiguring and pass an already-constructed NpgsqlDataSource to UseNpgsql.
Thanks @roji I wrote a data source resolver registered as a singleton, so now data sources are created only once:
DbContext:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connectionString = dbConfig
.Connection
.ConnectionString;
var dataSource = dataSourceResolver.Resolve(connectionString, BuildDataSource);
optionsBuilder.UseNpgsql(dataSource);
}
public class NpgsqlDataSourceResolver : INpgsqlDataSourceResolver
{
private readonly ConcurrentDictionary<string, NpgsqlDataSource> dataSources = new();
public NpgsqlDataSource Resolve(string connectionString, Func<string, NpgsqlDataSource> factory)
{
return dataSources.GetOrAdd(connectionString, factory);
}
}
Migration to .NET 8: Period Mapping and IServiceProvider Limit Issue
Environment
Description
I'm migrating multi-tenant services from .NET 6 to 8 and encountering issues with Period mapping and exceeding the IServiceProvider instance limit. Each tenant has a dedicated DB with read-and-write replicas (Domain and ReadModel DBcontexts).
Current Implementation
Based on this response, I updated my code as follows:
Domain Model
Service Registration
DB Context Configuration
Issue
While the Period mapping now works, I'm encountering the following error:
Even if I cache
NpgsqlDataSourceBuilder
instances per connection string, their number can still exceed the limit due to multiple tenants.Questions
Additional Context
Any guidance or suggestions would be greatly appreciated. Thank you!