如何将连接字符串正确存储在环境变量中,以便生产 ASP.Net 核心 MVC 应用程序进行检索



我正在开发一个 ASP.NET 核心MVC应用程序,我的连接字符串有问题。

我在生产服务器上设置了一个ASPNETCORE_ENVIRONMENT变量Production,我的生产服务器是运行 IIS 的 Windows Server 2012R2。我还在生产服务器上安装了DotNetCore.1.0.4_1.1.1-WindowsHosting.exe。

在开发过程中,我使用UserSecrets来保存我的连接字符串。这工作正常。

对于生产,我希望我的连接字符串位于生产服务器上的环境变量中,这就是我遇到问题的地方。我怀疑这可能是我构建环境变量的方式。

当我尝试在生产中访问数据库时,我收到一个错误,指示它基本上无法解析连接字符串。

An exception occurred in the database while iterating the results of a query.
System.ArgumentException: Keyword not supported: '"server'.
at System.Data.Common.DbConnectionOptions.ParseInternal(Dictionary`2 
parsetable, String connectionString, Boolean buildChain, Dictionary`2 synonyms)
at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Dictionary`2 synonyms)
at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)

如果我把连接字符串放在appSettings.json,生产服务器工作得很好。

因此,下面是我的appSettings.json文件的示例,其中显示了在生产中工作的连接字符串;

{
"ConnectionStrings": {
"TestDb": "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"
},
...
...
...
}
}

如果我将此appSettings.json文件部署到生产环境,它可以正常工作。

在我的 ASP.Net Core 应用程序中,在 Startup.cs 文件中,我有以下内容;

public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
// For more details on using the user secret store see https://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets<Startup>();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}

我的理解是,最后一个构建器.add...列出具有优先级,因此就我而言,如果环境中存在连接字符串,则它应优先于应用设置中的任何内容。

所以在生产中,如果我使用以下 appSettings.config 文件;

{
"ConnectionStrings": {
"TestDb": "Placeholder for connection string. Overridden by User Secrets in Development and Environment Variables in Production. "
},
...
...
...
}
}

如果我有连接字符串的环境变量,那么在该appsettings.json文件中ConnectionStrings:TestDb值应该无关紧要。

下面列出的是我正在使用的环境变量;

Variable                    Value
ConnectionStrings:TestDb    "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"

但是,当我使用此设置时,当我尝试访问数据库时出现错误,指示它无法分析连接字符串。

我必须假设问题是我在环境变量中指定的连接字符串的方式,但是在网上搜索了一段时间后,我无法找到环境变量值应该是什么样子的示例。例如,我是否需要在整个字符串周围加上前导和尾随单引号?连接字符串的各个部分是否需要单引号或双引号?

任何帮助,例如在环境变量中定义的正确连接字符串的示例,将不胜感激。

连接变量中设置了拼写错误/错误值。

这可以在您粘贴的输出中看到:

Variable                    Value
ConnectionStrings:TestDb    "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"

这可能发生在通过以下方式设置变量时

$env:ConnectionStrings:MyDb = """Server=..."""

正确的方法是设置它而不带引号。

$env:ConnectionStrings:MyDb = "Server=..."

旧答案(对于可能搜索类似问题的其他用户)

连接字符串的约定是 Azure Web 应用使用的SQLCONNSTR_MYSQLCONNSTR_SQLAZURECONNSTR_CUSTOMCONNSTR_,但也应适用于自托管、VM 或任何其他云提供商。

因此,如果您有一个名为CUSTOMCONNSTR_TestDb的环境变量,它将与在 appsettings.json 中定义它相同。

{
"connectionStrings": {
"TestDb": "..."
}
}

它还将覆盖其中的值,如果在.UseJsonFile(...)之后调用AddEnvironmentVariables()。最后注册获胜。

var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
// This one needs to be last
.AddEnvironmentVariables();

您还可以使用其他变量来覆盖配置值。ASPNETCORE_是默认前缀(但您可以在AddEnvironmentVariables("MY_")中更改它)。

因此,ASPNETCORE_MySettings覆盖Configuration["MySettings"](或Configuration.Get("MySettings"))和ASPNETCORE_My__Settings(在 Linux 上使用双下划线表示级别层次结构,阅读:用于获取配置的位置 - Linux 不允许变量名称中的冒号)覆盖Configuration["My:Settings"]

{
"my": {
"settings": "..."
}
}

除非他们最近改变了。

FWIW:据我所知,环境变量/配置键名称不区分大小写。

在您的配置中,您有以下行:

.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

这告诉您的配置系统可能存在一个 JSON 文件,其中包含特定于环境的设置。因此,您只需要生产框中存在的一个名为appSettings.Production.config的文件,其中包含如下内容:

{
"ConnectionStrings": {
"TestDb": "Server=...;Catalog=...;Etc=..."
}
}

此处的值将覆盖基本 JSON 设置文件中指定的任何内容。

如果您不想存储在应用程序设置中,请将其存储在文件中 C:\Windows\System32\inetsrv\config\applicationHost.config.它将能够工作。

最新更新