'How can I inject a service into an Entity Framework AddDbContextFactory lambda function in Blazor Server?
In Blazor server, how can I inject a scoped service into the lambda below so that I can read the authenticated user and select a SQL connection string based on the user.
builder.Services.AddDbContextFactory<GlueDbContext>((provider, options) =>
{
var AuthenticationStateProvider = provider.GetService<AuthenticationStateProvider>();
// *** Compiles but FAILS because AuthenticationStateProvider is not a Singleton ***
var user = _authenticationStateProvider.GetAuthenticationStateAsync().Result.User;
//
string sqlConnectString = SomeFunctionDerivingTheConnectionFromTheUser(user);
options.UseMySql(connectionString);
});
Solution 1:[1]
Following this link, it should look something like this (I'm typing without IDE so it may contain some typos):
var serviceScopeFactory = provider.GetService<IServiceScopeFactory>(); //IServiceScopeFactory is a singleton, so you can easily get it here
using var scope = serviceScopeFactory.CreateScope();
var authenticationStateProvider = scope.GetService<AuthenticationStateProvider>();
//...
Solution 2:[2]
You can't do that. Services.Add.... simply adds classes/interfaces to a collection. It's not till later that the services container gets initialised, and until you use a DI object that an instance of that object gets initialised.
To illustrate the process, here's the code to set up a services container serviceProvider in a test.
var services = new ServiceCollection();
services.AddDbContextFactory<InMemoryWeatherDbContext>(options => options.UseInMemoryDatabase("WeatherDatabase"));
services.AddSingleton<IDataBroker, ServerDataBroker>();
var serviceProvider = services.BuildServiceProvider();
Whatever you design, it needs rethinking. You can't get a user until an SPA session has initialized.
Solution 3:[3]
AddDbContextFactory has a defaulted parameter set to Singleton. add ServiceLifetime.Scoped
builder.Services.AddDbContextFactory<GlueDbContext>((provider, options) =>
{
var AuthenticationStateProvider = provider.GetService<AuthenticationStateProvider>();
var user = _authenticationStateProvider.GetAuthenticationStateAsync().Result.User;
string sqlConnectString = SomeFunctionDerivingTheConnectionFromTheUser(user);
options.UseMySql(connectionString);
}, ServiceLifetime.Scoped);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | KifoPL |
| Solution 2 | |
| Solution 3 | Discovery-Support |
