Using ApplicationDbContext with DI from appsettings.json

I am trying to divert any connection information from the ApplicationDbContext class so that I can use different databases for development, staging, production. I start by registering a service from Startup.cs

services.AddDbContext<ApplicationDbContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

      

My ApplicationDbContext class:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
     : base(options)
   {
   }

    protected override void OnModelCreating(ModelBuilder builder)
    {
         base.OnModelCreating(builder);
    }
}

      

I am getting the following error when running this application:

InvalidOperationException . Failed to create an instance of type SquadApps.Data.ApplicationDbContext. Model-related complex types must not be abstract or value types and must have a parameterless constructor.

So naturally I tried to add a parameterless constructor

public ApplicationDbContext() { } 

      

Now we get another error:

InvalidOperationException : No database provider has been configured for this DbContext. The provider can be customized by overriding the DbContext.OnConfiguring method or by using AddDbContext from the application service provider. If using AddDbContext, then also make sure that your DbContext type takes a DbContextOptions object in its constructor and passes it to the base constructor for the DbContext.

If I go back to the connection string stored in the ApplicationDbContext class like:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer("........");
}

      

Then everything works fine, but obviously this is not ideal and probably bad practice. I think there is something that I am missing in the DI process and any suggestions or advice would be appreciated.

+3


source to share


1 answer


The solution turned out to be what I tried to call DI. I incorrectly assumed that DI could be called for every IActionResult inside my controllers, but in fact it should happen inside the constructorcontroller. This makes the DI available to all IActionResult methods in the controller.

An example of a DI work call:



public class HomeController : Controller
{
    private readonly ApplicationDbContext _ctx;
    private readonly CompanySettings _companySettings;

    public HomeController(ApplicationDbContext ctx, IOptions<CompanySettings> settings)
    {
        _ctx = ctx;
        _companySettings = settings.Value;
    }

    public IActionResult Index()
    {
        var model = new HomeViewModel();

        // _ctx and _companySettings can be used here

        return View(model);
    }
}

      

+1


source







All Articles