al.koval
al.koval

Reputation: 2542

EF Core how to get a DBContext in a class instance?

The ASP NET Core project uses the Entity Framework Core.

From the method of the Home controller I call Task.Run for the method of the instance of the class MyClass, where I need to access the data from the database.

I tried to pass _dbContext to the constructor of the MyClass class, but I get the exception

Cannot access a disposed object.

HomeController

[Route("api/[controller]")]
[EnableCors("AllowAllOrigin")]
[ApiController]
public class HomeController : ControllerBase
{
   private readonly DataBaseContext _dbContext;

   public HomeController (DataBaseContext dbContext)
   {
      _dbContext = dbContext;
   }

   [EnableCors("AllowAllOrigin")]
   [HttpPost("[action]")]
   public string UpdateBotSettings()
   {
      MyClass myClass = new MyClass(_dbContext);
      Task task = Task.Run(() => myClass.AnyMethod());
   }
}

MyClass

public class MyClass
{
   private readonly DataBaseContext _dbContext;

   public MyClass(DataBaseContext dbContext)
   {
      _dbContext = dbContext;
   }

   public async void AnyMethodAsync()
   {
      MyData myData = _dbContext.AnyData.Where(d => d.id == 1).FirstOrDefault(); // <- exception
   }
}

Startup

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

  string connection = Configuration.GetConnectionString("ConnectionDB");
  services.AddDbContext<DataBaseContext>(options =>  options.UseSqlServer(connection));
  // another code
}

Can you please tell me how to access dbContext inside an instance of MyClass?

Upvotes: 1

Views: 6419

Answers (1)

TanvirArjel
TanvirArjel

Reputation: 32119

Most important mistake in your code is that you are using async void in your AnyMethodAsync() method of the Myclass. Don't use async void in your code, instead use async Task. Here is the details: C# – beware of async void in your code

So write your AnyMethodAsync() as follows:

public async Task AnyMethodAsync()
{
   MyData myData = await _dbContext.AnyData.Where(d => d.id == 1).FirstOrDefault(); 
}

Now you can register your MyClass to the ASP.NET Core DI container as follows:

public void ConfigureServices(IServiceCollection services)
{
   services.AddScoped<MyClass>(); // <-- here it is

   string connection = Configuration.GetConnectionString("ConnectionDB");
   services.AddDbContext<DataBaseContext>(options =>  options.UseSqlServer(connection));
   // another code
   services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Now use it as follows:

[Route("api/[controller]")]
[EnableCors("AllowAllOrigin")]
[ApiController]
public class HomeController : ControllerBase
{
   private readonly DataBaseContext _dbContext;
   private readonly MyClass _myClass

   public HomeController (DataBaseContext dbContext, MyClass myClass)
   {
      _dbContext = dbContext;
      _myClass = myClass;
   }

   [EnableCors("AllowAllOrigin")]
   [HttpPost("[action]")]
   public async Task<string> UpdateBotSettings()
   {
      await _myClass.AnyMethod();

      // rest of codes
   }
}

Upvotes: 1

Related Questions