Home > Back-end >  .NET Core 6 inject databasecontext to Singleton Service
.NET Core 6 inject databasecontext to Singleton Service

Time:09-06

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:

  1. 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);
  1. 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
        }
    }
}
  • Related