Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use DbContext in ASP .Net Singleton Injected Class

I need to access my database in a Singleton class instantiated in my Startup class. It seems that injecting it directly results in a DbContext that is disposed.

I get the following error:

Cannot access a disposed object. Object name: 'MyDbContext'.

My question is twofold: Why doesn't this work and how can I access my database in a singleton class instance?

Here is my ConfigureServices method in my Startup class:

public void ConfigureServices(IServiceCollection services) {     // code removed for brevity      services.AddEntityFramework().AddSqlServer().AddDbContext<MyDbContext>(         options =>         {             var config = Configuration["Data:DefaultConnection:ConnectionString"];             options.UseSqlServer(config);         });      // code removed for brevity      services.AddSingleton<FunClass>(); } 

Here is my controller class:

public class TestController : Controller {     private FunClass _fun;      public TestController(FunClass fun)     {         _fun = fun;     }      public List<string> Index()     {         return _fun.GetUsers();     } } 

Here is my FunClass:

public class FunClass {     private MyDbContext db;      public FunClass(MyDbContext ctx) {         db = ctx;     }      public List<string> GetUsers()     {          var lst = db.Users.Select(c=>c.UserName).ToList();         return lst;     } } 
like image 446
Tjaart Avatar asked Mar 31 '16 11:03

Tjaart


People also ask

Can DbContext be singleton?

First, DbContext is a lightweight object; it is designed to be used once per business transaction. Making your DbContext a Singleton and reusing it throughout the application can cause other problems, like concurrency and memory leak issues.

Is DbContext scoped or transient?

This example registers a DbContext subclass called ApplicationDbContext as a scoped service in the ASP.NET Core application service provider (a.k.a. the dependency injection container). The context is configured to use the SQL Server database provider and will read the connection string from ASP.NET Core configuration.

Can we use singleton as DbContext's lifetime?

Popular Answer. DbContext should not be used as a singleton because it is holding a connection object which cannot be used by multiple threads at the same time. You will run into errors if two requests try to use it at the same time. If your service depends on the context, the service cannot be a singleton.


1 Answers

Original source: https://entityframeworkcore.com/knowledge-base/51939451/how-to-use-a-database-context-in-a-singleton-service-

Since DbContext is scoped by default, you need to create scope to access it. It also allows you to handle its lifetime correctly - otherwise you'd keep instance of DbContext for a long time and this is not recommended.

public class Singleton : ISingleton  {      private readonly IServiceScopeFactory scopeFactory;      public Singleton(IServiceScopeFactory scopeFactory)     {         this.scopeFactory = scopeFactory;     }      public void MyMethod()      {         using(var scope = scopeFactory.CreateScope())          {             var db = scope.ServiceProvider.GetRequiredService<DbContext>();              // when we exit the using block,             // the IServiceScope will dispose itself              // and dispose all of the services that it resolved.         }     } } 
like image 57
Spook Avatar answered Sep 21 '22 05:09

Spook