简体   繁体   English

使用ApplicationDbContext和来自appsettings.json的DI

[英]Using ApplicationDbContext with DI from appsettings.json

I am trying to abstract any connection information away from my ApplicationDbContext class so that I can take advantage of different databases for development, staging, production. 我试图从我的ApplicationDbContext类中抽象出任何连接信息,以便我可以利用不同的数据库进行开发,登台,生产。 I start by registering a service from Startup.cs 我首先从Startup.cs注册一个服务

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

My ApplicationDbContext class: 我的ApplicationDbContext类:

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

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

When running this application I get the following error: 运行此应用程序时,我收到以下错误:

InvalidOperationException : Could not create an instance of type 'SquadApps.Data.ApplicationDbContext'. InvalidOperationException :无法创建“SquadApps.Data.ApplicationDbContext”类型的实例。 Model bound complex types must not be abstract or value types and must have a parameterless constructor. 模型绑定的复杂类型不能是抽象或值类型,并且必须具有无参数构造函数。

So naturally I tried adding a parameterless constructor 所以我很自然地尝试添加无参数构造函数

public ApplicationDbContext() { } 

Now getting another error: 现在又出现了另一个错

InvalidOperationException : No database provider has been configured for this DbContext. InvalidOperationException :尚未为此DbContext配置任何数据库提供程序。 A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. 可以通过覆盖DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext来配置提供程序。 If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext. 如果使用AddDbContext,那么还要确保您的DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基础构造函数。

If I go back to having a connection string stored in the ApplicationDbContext class like so: 如果我回到在ApplicationDbContext类中存储连接字符串,如下所示:

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

Then everything works fine but obviously this is not ideal and probably a bad practice. 然后一切正常,但显然这不是理想的,可能是一个不好的做法。 I think there is something i'm missing about the DI process and any suggestions or advice would be appreciated. 我认为DI过程中缺少一些东西,任何建议或建议都会受到赞赏。

The solution turned out to be how I was trying to call the DI. 解决方案原来是我试图调用DI的方式。 I had incorrectly assumed DI would be able to be called per each IActionResult inside my controllers but in fact it must occur within the constructor of the controller. 我错误地假设DI可以在我的控制器内的每个IActionResult中调用,但实际上它必须在控制器的构造函数中发生。 This makes the DI available to all IActionResult methods within the controller. 这使得DI可用于控制器内的所有IActionResult方法。

Example of the working DI call: 工作DI呼叫的示例:

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM