Here is my setup: Blazor Server app with .NET 7.
I have the following question. I'm using built-in dependency injection from .NET.
...
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
//Models
builder.Services.AddScoped<IEnvironment, ApplicationLogic.Models.Environment>();
//Database
builder.Services.AddTransient<IDbConnectionString, DbConnectionString>();
builder.Services.AddTransient<IIMP_GG_Context, IMP_GG_Context>();
...
I'm using Entity Framework Core for the connection to the database.
Now I have the situation, that in my application the user is able to choose between different environments ("Live", "Test", "Development").
A change of the environment should change the connection to the database which is being used.
The selected enviroment is being save in an Enviroment
object and has only one property which is an enum
.
The environment setup is Scoped
.
builder.Services.AddScoped<IEnvironment, ApplicationLogic.Models.Environment>();
So here is the current structure of my application based on one example (ProductStatus
).
The UI have injected a controller object. Here is an example (see _ProductStatusController
):
public partial class Filter
{
...
[Inject] private IProductStatusController _ProductStatusController { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
GetAllProductStatus();
}
private void GetAllProductStatus()
{
var productStatus = _ProductStatusController.GetAllProductStatus();
...
}
...
}
The controller has a repository injected.
public class ProductStatusController : IProductStatusController
{
private IProductStatusRepository _ProductStatusRepository;
public ProductStatusController(IProductStatusRepository productStatusRepository)
{
_ProductStatusRepository = productStatusRepository;
}
public List<Vorlauf> GetAllProductStatus()
{
return _ProductStatusRepository.GetAll();
}
}
The Repository (ProductStatusRepository
) looks like this. Here is the Entity framework core context object (_Context
) (also injected).
public class ProductStatusRepository : IProductStatusRepository
{
private IIMP_GG_Context _Context;
public ProductStatusRepository(IIMP_GG_Context impGgContext)
{
_Context = impGgContext;
}
public List<Vorlauf> GetAll()
{
return _Context.VorlaufTable.Where((vorlauf) => vorlauf.Art == 62).ToList();
}
}
Which connection is being used, depends on the object Environment
.
Here is the Context
class:
public class IMP_GG_Context : DbContext, IIMP_GG_Context
{
public DbSet<Vorlauf> VorlaufTable { get; set; }
... //more tables
DbConnection _Connection;
IDbConnectionString _DbConnectionString;
IEnvironment _Environment;
public IMP_GG_Context(IDbConnectionString dbConnectionString)
{
_DbConnectionString = dbConnectionString;
Database.SetCommandTimeout(600);
}
public IMP_GG_Context(DbConnection connection, IDbConnectionString dbConnectionString)
{
_DbConnectionString = dbConnectionString;
_Connection = connection;
}
~IMP_GG_Context()
{
}
private void OnEnvironmentChanged(object sender, PropertyChangedEventArgs e)
{
OnConfiguring(new DbContextOptionsBuilder());
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (_Connection == null)
{
string connection = _DbConnectionString.GetImpGgConnectionString();
optionsBuilder.UseSqlServer(connection);
}
else
{
optionsBuilder.UseSqlServer(_Connection);
}
}
}
The _DbConnectionString
property offers a method to get the correct connection string based on the chosen environment.
I think, the issue I have now, is that the _ProductStatusController
object is once created when the UI component is being created. So the database connection will be created only once and not being updated when the environment changes.
Is there any solution to this? What can I do to re-create the _ProductStatusController
object?
Many thanks in advance.
UPDATE
I tried the provided solution of Svyatoslav Danyliv. But it actually resets my selected environment to the default (="Test").
This is the new code I'm using in my Filter UI:
private void GetAllProductStatus()
{
using (var scope = _ServiceProvider.CreateScope())
{
var environment = scope.ServiceProvider.GetRequiredService<IEnvironment>();
environment = _Environment;
var productStatusController = scope.ServiceProvider.GetRequiredService<IProductStatusController>();
var productStatus = productStatusController.GetAllProductStatus();
...
}
}
As you can see the environment is set correctly at this stage (="Dev"):
But when I execute the next step
var productStatusController = scope.ServiceProvider.GetRequiredService<IProductStatusController>();
...the environment is being resetted to "Test":
Am I doing here something wrong?