在StartUp类的ASP.Net MVC Core的配置方法中," IHostingEnvironment env"通过依赖注入传入。 并且可以基于环境做出决定。例如,
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
在ConfigureServices中,我想做类似这样的事情来选择正确的连接字符串。 类似的东西:
if (env.IsDevelopment())
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
else if (env.IsStaging())
{
// Add Staging Connection
}
else
{
// Add Prod Connection
}
但是&#34; IHostingEnvironment env&#34;默认情况下不传递给ConfigureServices方法。 所以我修改了签名:
public void ConfigureServices(IServiceCollection services)
到
public void ConfigureServices(IServiceCollection services, IHostingEnvironment env)
并在ConfigureServices中输入:
if (env.IsDevelopment())
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
else if (env.IsStaging())
{
// Add Staging Connection
}
else
{
// Add Prod Connection
}
所以现在我跑的时候会收到以下错误消息:
&#34; ConfigureServices方法必须是无参数的,或者只接受IServiceCollection类型的一个参数。&#34;
ConfigureServices()不会接受IHostingEnvironment var。
但是&#34; Startup.StartUp(IHostingEnvironment env)&#34;确实。 我考虑添加一个StartUp类字段并从Startup()将其设置为正确的环境,然后使用该字段在ConfigureServices中创建决策流。但这似乎是一个黑客。
我知道环境是.Net Core中的一流概念。 有没有办法直接从appsetting.json做到这一点?
实现这一目标的最佳做法是什么?
答案 0 :(得分:3)
<强>更新强> 就像萨姆所说,乔的解决方案虽然运作正常,但这是一个黑客攻击。从ASP.Net Core 1.1开始,对不同环境使用不同连接的正确方法是从appsettings.json文件本身处理它,而不是在ConfigureServices方法中检查环境。默认情况下,该项目附带 appsettings.json 和 appsettings.Development.json 文件(如果需要,可以使用命名约定手动创建另一个用于Staging的文件)< / p>
因此,在Joe的解决方案中,您不需要在构造函数中设置环境的值,也不需要使用它来在ConfigurServices中检查它的托管环境。所以摆脱:
environment = env;
........
public IHostingEnvironment environment {get;组; }
........
//另外,在ConfigureServices方法中删除if / else。
所以你的ConfigureServices方法只会注入:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
现在,您的 appsettings.json 将包含:
"ConnectionStrings": {
"DefaultConnection": "//Value of your connection string for Production Env."
}
您的 appsettings.Development.json 将有:
"ConnectionStrings": {
"DefaultConnection": "//Value of your connection string for Development Env."
}
现在,如果你看一下构造函数方法,var builder 已经加载了两个appsettings文件,并且根据你是在开发环境还是已发布的生产环境中运行项目,它将使用正确的文件因此在它们中定义了设置。
答案 1 :(得分:2)
IHostingEnvrionment被传递到Startup的构造函数中,从那里你可以将它持久保存到属性然后从ConfigureSerivces中使用它
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
// add this file name to your .gitignore file
// so you can create it and use on your local dev machine
// remember last config source added wins if it has the same settings
builder.AddJsonFile("appsettings.dev.json", optional: true);
builder.AddEnvironmentVariables();
Configuration = builder.Build();
environment = env;
}
public IHostingEnvironment environment { get; set; }
public void ConfigureServices(IServiceCollection services)
{
if (envirnoment.IsDevelopment())
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
else if (envirnoment.IsStaging())
{
// Add Staging Connection
}
else
{
// Add Prod Connection
}
}
答案 2 :(得分:0)
你也可以利用Environment based Startup class and methods来解决这个问题。所以,你可以这样做:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ProductionConnection")));
}
public void ConfigureStagingServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("StagingConnection")));
}
public void ConfigureDevelopmentServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
就环境之间的常见服务而言,您可以将它们提取到私有方法中,然后在Configure {Environment} Services上调用它。另外,请考虑在源代码管理中没有生产连接字符串。您可以将其设置为Environment Variable on the machine.