Singleton with DbContext - instantiating in Startup.cs
I am using ASP.net core. I have a problem implementing dbcontext in singleton.
I need my singleton IModuleRepository to work right after starting the project. So I create a new instance of this dependency in a file public void ConfigureServices(IServiceCollection services)
in Startup.cs
.
This singleton is using another singleton, so I use it like this:
services.AddDbContext<ModulesDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")).EnableSensitiveDataLogging());
...
services.AddSingleton<IModuleRepository, ModuleRepository>();
services.AddSingleton<ICommunicationRepository>(new CommunicationRepository(services.BuildServiceProvider().GetService<IModuleRepository>()));
In the ModuleRepository, I am using DBcontext.
// Db context
private readonly ModulesDbContext _modulesDbContext;
public ModuleRepository(ModulesDbContext modulesDbContext)
{
_modulesDbContext = modulesDbContext;
}
When I call _modulesDbContext.SomeModel.ToList();
, I get an error:
System.InvalidOperationException: An attempt was made to use the context while configuring it. The DbContext instance cannot be used inside OnConfiguring because it is still configured at this point.
How can I avoid this error when I need this singleton to run after starting the project?
Thank you for your help.
source to share
I figured out this problem. This dependency requirement was correct. The error is that in CommunicationRepository I created 2 Tasks and they both used the same DbContext - so it used it multiple times. I should have saidtask.Wait();
Full code in CommunicationRepository constructor after fix:
// Add pernament communication
var task = new Task(AddPernamentCommunicationAll);
task.Start();
task.Wait();
// Add modules
var taskModules = new Task(AddModulesToList);
taskModules.Start();
Thank you for your responses.
source to share
As @Ilya Chumakov commented, you can simply tell the DI container to use its specific class like this:
services.AddSingleton<ICommunicationRepository, CommunicationRepository>();
Then any class can depend on ICommunicationRepository
and get a specific repository that gets the Db context.
source to share