Как правильно хранить строки подключения в переменных среды для извлечения по продуктам ASP.Net Core MVC-приложения
Я работаю над ASP.NET Core MVC-приложением, и у меня возникла проблема с моими строками подключения.
У меня есть переменная ASPNETCORE_ENVIRONMENT
установленная для Production
на моем ASPNETCORE_ENVIRONMENT
сервере, а мой производственный сервер - это Windows Server 2012R2, работающий с IIS. У меня также есть 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();
}
Я понимаю, что последний список builder.add... имеет приоритет, поэтому в моем случае, если в среде существует строка соединения, она должна иметь приоритет над чем-либо в настройках appsettings.
Поэтому в производстве, если я использую следующий файл appSettings.config;
{
"ConnectionStrings": {
"TestDb": "Placeholder for connection string. Overridden by User Secrets in Development and Environment Variables in Production. "
},
...
...
...
}
}
Не имеет значения, что у меня есть значение для ConnectionStrings:TestDb
в этом файле appsettings.json
если у меня есть переменная среды для строки подключения.
Ниже приведена переменная среды, которую я использую;
Variable Value
ConnectionStrings:TestDb "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"
Однако, когда я использую эту настройку, я получаю сообщение об ошибке при попытке доступа к базе данных, указывающей на то, что она не может разобрать строку подключения.
Я должен предположить, что проблема заключается в том, как у меня есть строка соединения, указанная в переменной среды, но после долгого поиска в Интернете я не смог найти пример того, как должно выглядеть значение переменной среды. Например, мне нужно поставить ведущие и конечные одинарные кавычки вокруг всей строки? Нужны ли отдельные разделы строки соединения одинарные или двойные кавычки?
Любая помощь, такая как пример правильной строки соединения, определенной в переменной среды, будет с большой благодарностью.
Ответы
Ответ 1
В ваших переменных соединения есть опечатка/неправильное значение.
Что можно увидеть в этом выпуске, который вы вставили:
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=..."
Старый ответ (для других пользователей, которые могут искать похожие проблемы)
Соглашением для строк подключения являются SQLCONNSTR_
, MYSQLCONNSTR_
, SQLAZURECONNSTR_
и CUSTOMCONNSTR_
которые используются Azure Web Apps, но также должны работать для самостоятельного хостинга, виртуальных машин или любого другого облачного провайдера.
Поэтому, если у вас есть переменная среды, называемая CUSTOMCONNSTR_TestDb
она будет такой же, как и ее определение в appsettings.json в
{
"connectionStrings": {
"TestDb": "..."
}
}
Он также переопределяет значение внутри него, если AddEnvironmentVariables()
вызывается после .UseJsonFile(...)
. Последняя регистрация выигрывает.
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();
Вы также можете использовать другие переменные для переопределения значений конфигурации. IIRC. ASPNETCORE_
является префиксом по умолчанию (но вы можете изменить его в AddEnvironmentVariables("MY_")
).
Таким образом, ASPNETCORE_MySettings
переопределяет Configuration["MySettings"]
(или Configuration.Get("MySettings")
) и ASPNETCORE_My__Settings
(используйте двойной подчеркивание для иерархии уровней в Linux, читайте где :
используется для получения конфигурации - Linux запрещает двоеточие в именах переменных) переопределяет Configuration["My:Settings"]
так же, как
{
"my": {
"settings": "..."
}
}
Если они не изменились в последнее время.
FWIW: Переменные среды/имена ключей конфигурации нечувствительны к регистру, насколько я помню.
Ответ 2
В вашей конфигурации у вас есть эта строка:
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
Это говорит вашей системе настройки, что в нем может быть JSON файл, который существует с настройками среды. Таким образом, вам нужен только файл, который существует в поле производства appSettings.Production.config
содержащее что-то вроде этого:
{
"ConnectionStrings": {
"TestDb": "Server=...;Catalog=...;Etc=..."
}
}
Значения здесь будут переопределять все, что указано в базовом файле настроек JSON.
Ответ 3
если вы не хотите хранить в appsettings, сохраните его в файле C:\Windows\System32\inetsrv\config\applicationHost.config. Он сможет работать.