Как настроить конфигурацию строки подключения программно в .net?
Я хотел бы установить строку соединения программно, без каких-либо изменений в конфигурационных файлах/ключах реестра.
У меня есть этот фрагмент кода, но, к сожалению, он генерирует исключение с "конфигурацией только для чтения".
ConfigurationManager.ConnectionStrings.Clear();
string connectionString = "Server=myserver;Port=8080;Database=my_db;...";
ConnectionStringSettings connectionStringSettings =
new ConnectionStringSettings("MyConnectionStringKey", connectionString);
ConfigurationManager.ConnectionStrings.Add(connectionStringSettings);
Edit:
Проблема в том, что у меня есть существующий код, который считывает строку соединения из конфигурации. Поэтому настройка строки конфигурации вручную или через ресурс не кажется допустимым. Мне действительно нужен способ изменения конфигурации программно.
Ответы
Ответ 1
Я написал об этом в сообщении в своем блоге. Фокус в том, чтобы использовать отражение для обозначения значений в качестве способа получить доступ к непубличным полям (и методам).
например.
var settings = ConfigurationManager.ConnectionStrings[ 0 ];
var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic );
fi.SetValue(settings, false);
settings.ConnectionString = "Data Source=Something";
Ответ 2
Я искал ответ на тот же вопрос о том, как разрешить пользователю изменять строку подключения в однократном приложении, выбрав локальный SQL Server.
В приведенном ниже коде представлена форма пользователя, которая связывается со всеми локально доступными SQL-серверами и позволяет им выбрать один из них. Затем он строит строку соединения для этого сегмента и возвращает ее из переменной в форме. Затем код изменяет конфигурационные файлы и сохраняет его.
string NewConnection = "";
// get the user to supply connection details
frmSetSQLConnection frm = new frmSetSQLConnection();
frm.ShowDialog();
if (frm.DialogResult == DialogResult.OK)
{
// here we set the users connection string for the database
// Get the application configuration file.
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get the connection strings section.
ConnectionStringsSection csSection = config.ConnectionStrings;
foreach (ConnectionStringSettings connection3 in csSection.ConnectionStrings)
{
// Here we check for the preset string - this could be done by item no as well
if (connection3.ConnectionString == "Data Source=SQL204\\SQL2008;Initial Catalog=Transition;Integrated Security=True")
{
// amend the details and save
connection3.ConnectionString = frm.Connection;
NewConnection = frm.Connection;
break;
}
}
config.Save(ConfigurationSaveMode.Modified);
// reload the config file so the new values are available
ConfigurationManager.RefreshSection(csSection.SectionInformation.Name);
return clsDBMaintenance.UpdateDatabase(NewConnection))
}
Ответ 3
Еще один способ приблизиться к этому - это напрямую работать с коллекцией:
var settings = ConfigurationManager.ConnectionStrings;
var element = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
var collection = typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
element.SetValue(settings, false);
collection.SetValue(settings, false);
settings.Add(new ConnectionStringSettings("ConnectionStringName", connectionString));
// Repeat above line as necessary
collection.SetValue(settings, true);
element.SetValue(settings, true);
Ответ 4
Я считаю, что это работает для меня:
Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
ConnectionStringsSection section = config.GetSection("connectionStrings") as ConnectionStringsSection;
if (section != null)
{
section.ConnectionStrings["MyConnectionString"].ConnectionString = connectionString;
config.Save();
}
Это перезаписывает существующую строку подключения.
Ответ 5
В настоящее время я использую инъекцию зависимостей для обработки различных строк подключения в средах dev/prod и test. Мне все равно придется вручную изменить webconfig, если я хочу перейти на dev и prod, но для тестирования у меня есть интерфейс IConnectionStringFactory с реализацией по умолчанию, которая просматривает веб-конфигурацию и альтернативную конфигурацию тестирования, которая возвращает статические значения. Таким образом, когда я тестирую, я просто устанавливаю factory в реализацию тестирования, и он вернет тестовую строку подключения для ключа, который я прошу. В противном случае он будет выглядеть в webconfig.
Я мог бы расширить это до другой реализации для dev vs. prod, но мне более удобно иметь единственную реализацию IConnectionStringFactory в моей сборке и реализацию тестирования в моей тестовой сборке.
Ответ 6
Вместо этого вы можете поместить его в файл ресурсов. Он не будет иметь встроенных функций класса ConfigurationManager, но он будет работать.
Предполагая, что Resources.resx:
Resources.Default.ConnectionString = "Server=myserver;" // etc
Затем в вашем коде:
conn.ConnectionString = Resources.Default.ConnectionString
Это хак, я знаю.
Ответ 7
В дополнение к другим приведенным ответам и при условии, что строка подключения не является просто другой конфигурационной переменной или константой в целом, вы можете рассмотреть возможность использования класса SqlConnectionStringBuilder вместо прямой конкатенации строки вместе.
РЕДАКТИРОВАТЬ: Ups, извините, только что увидел, что вы в основном хотите прочитать строку подключения (я думаю, завершена) из другого источника.
Ответ 8
Похоже, что имя изменилось с .net Core 2.1 Изменение ответа Дэвида Гардинера Этот способ должен работать для ссылок на новые и старые версии:
var settings = ConfigurationManager.ConnectionStrings [0];
var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic );
if(fi == null)
{
fi = typeof(System.Configuration.ConfigurationElementCollection).GetField("_readOnly", BindingFlags.Instance | BindingFlags.NonPublic);
}
fi.SetValue(settings, false);
settings.ConnectionString = "Data Source=Something";
Ответ 9
ConfigurationManager используется для чтения из файла конфигурации.
Ваше решение состоит в том, чтобы просто установить conn.ConnectionString в нужную строку связи.