如何在 .Net Core 启动中根据环境动态选择连接字符串?

Sam*_*Sam 2 asp.net-mvc asp.net-core

在ASP.Net MVC Core的StartUp类的Configure方法中,“IHostingEnvironment env”是通过依赖注入传入的。并且可以根据环境做出决定。例如,

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
Run Code Online (Sandbox Code Playgroud)

在 ConfigureServices 中,我想做这样的事情来选择正确的连接字符串。就像是:

        if (env.IsDevelopment())
        {
            services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
        }
        else if (env.IsStaging())
        {
            // Add Staging Connection
        }
        else
        {
            // Add Prod Connection
        }
Run Code Online (Sandbox Code Playgroud)

但默认情况下,“IHostingEnvironment env”不会传递给 ConfigureServices 方法。所以我修改了签名:

public void ConfigureServices(IServiceCollection services)
Run Code Online (Sandbox Code Playgroud)

public void ConfigureServices(IServiceCollection services, IHostingEnvironment env)
Run Code Online (Sandbox Code Playgroud)

并在 ConfigureServices 中放置:

        if (env.IsDevelopment())
        {
            services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
        }
        else if (env.IsStaging())
        {
            // Add Staging Connection
        }
        else
        {
            // Add Prod Connection
        }
Run Code Online (Sandbox Code Playgroud)

所以现在当我运行时,我收到此错误消息:

“ConfigureServices 方法要么是无参数的,要么只接受一个 IServiceCollection 类型的参数。”

ConfigureServices() 不会接受 IHostingEnvironment 变量。

但是“Startup.StartUp(IHostingEnvironment env)”可以。我想过添加一个 StartUp 类字段并将其从 Startup() 设置为正确的环境,然后使用该字段在 ConfigureServices 中做出决策流。但这似乎是一个黑客。

我知道环境是 .Net Core 中的一流概念。有没有办法直接从 appsetting.json 做到这一点?

实现这一目标的最佳实践是什么?

Cap*_*Red 5

更新 就像 Sam 所说的,Joe 的解决方案虽然工作正常,但这是一个 hack。从 ASP.Net Core 1.1 开始,针对不同环境使用不同连接的正确方法是从 appsettings.json 文件本身处理它,而不是在 ConfigureServices 方法中检查环境。该项目默认带有appsettings.jsonappsettings.Development.json文件(如果需要,可以使用命名约定手动创建一个不同的 Staging 文件)

因此,在 Joe 的解决方案中,您不需要在构造函数中设置环境的值,也不需要使用它来检查 ConfigurServices 中的托管环境。所以摆脱:

环境 = 环境;
…………

公共 IHostingEnvironment 环境 { 获取;放; }
........
//另外,去掉ConfigureServices方法中的if /else。

所以你的 ConfigureServices 方法只会注入:

services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
Run Code Online (Sandbox Code Playgroud)

现在,您的appsettings.json将具有:

  "ConnectionStrings": {
    "DefaultConnection": "//Value of your connection string for Production Env."
  }
Run Code Online (Sandbox Code Playgroud)

并且您的appsettings.Development.json将具有:

"ConnectionStrings": {
        "DefaultConnection": "//Value of your connection string for Development Env."
      }
Run Code Online (Sandbox Code Playgroud)

现在,如果您查看构造函数方法,var builder已经加载了两个 appsettings 文件,并且取决于您是在开发环境还是已发布的生产环境中运行项目,它将使用正确的文件,从而使用其中定义的设置。