I have a problem when try to use database context in one Singleton Service in my app.
App.cs
...
var service = builder.Services;
service.AddDbContext<MyDBContext>(options => options.UseSqlite(connectionString));
service.AddSingleton<MyMonitorManager>();
...
MyDBContext.cs
public class MyDBContext : ApiAuthorizationDbContext<ApplicationUser>
{
public DroneDBContext(...): base(options, operationalStoreOptions){}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){}
protected override void OnModelCreating(ModelBuilder modelBuilder){}
}
MyMonitorManager.cs
public class MyMonitorManager {
private readonly MyDBContext _databaseManager;
...
}
There are errors:
Cannot consume scoped service 'MyController.MyDBContext' from singleton 'MyController.Service.MyMonitorManager'.
I try to search here and think about use like this:
MyDBContext dbContext = new MyDBContext();
service.AddSingleton(new MyMonitorManager(dbContext));
But not sure this is how I should do in .NET 6
CodePudding user response:
You can use IServiceScopeFactory in your singleton class to create a new scope, and then get a db context reference from that:
public class MyMonitorManager {
private readonly IServiceScopeFactory _scopeFactory;
public MyMonitorManager(IServiceScopeFactory _scopeFactory)
{
_scopeFactory = scopeFactory;
}
public SomeMethod()
{
using (var scope = _scopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<MyDBContext>();
...
}
}
}
CodePudding user response:
You can't inject directly scoped service into singleton, you have follwoing options:
- Register database context with different lifetime, though in general case it is not the best option:
service.AddDbContext<MyDBContext>(options => options.UseSqlite(connectionString), ServiceLifetime.Transient);
- Inject
IServiceScopeFactory
to create scope and resolve context when needed the singleton service:
public class MyMonitorManager
{
private readonly IServiceScopeFactory _scopeFactory;
public class MyMonitorManager(IServiceScopeFactory scopeFactory) => _scopeFactory = scopeFactory;
public void SomeMethod()
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var ctx = scope.ServiceProvider.GetService<MyDBContext>();
// use context
}
}
}