Scenario
In the server project of a Blazor web assembly application, I have a service that will utilize certain metadata from the database. This metadata will only change with changes to the schema - not during normal application execution.
My intent is to create a singleton service that can be called from a controller to access this information. I intend to capture this metadata once and then make it available through the service.
I believe the way to do this is to make the DbContext
available within the constructor of the service, capture the information, and then destroy the DbContext
as it will not be needed again within the service. Other methods will pass this metadata to the caller.
Question 1
Does this approach make sense? The basic logic will be:
public ServiceConstructor()
{
// Get copy of the dbcontext
// Do some work using the dbcontext
// destroy the dbcontext.
}
Question 2
How do I go about getting a copy of the DbContext
from the scoped service and does it make sense to do this without passing it in to the constructor as a parameter?
My approach would be to cache the data in a Singleton Service, but access it through a Scoped Service.
The first Scoped Service to access the data finds it empty so gets it using a DBContext from the DbContextFactory
. Thereafter any further scoped services access the data cached in the Singleton.
I wouldn't pass a DbContext
into the singleton for it to use.
Something like:
public class DataSingletonService
{
internal string? Value { get; private set; }
internal void SetData(string value)
=> Value = value;
}
And
public class DataScopedService
{
private DataSingletonService _dataSingletonService;
// define the DBContextFactory here
public DataScopedService(DataSingletonService dataSingletonService)
{
// Get the DBContextFactory here
_dataSingletonService = dataSingletonService;
}
public async ValueTask<string> GetDataAsync()
{
if (_dataSingletonService.Value is null)
{
// using dbContext = DbContextFactory.GetContext();
// fake a db async call to the DbContext
await Task.Delay(500);
_dataSingletonService.SetData("Now Set");
}
return _dataSingletonService.Value ?? string.Empty;
}
}