Как установить конфигурацию строки подключения программно in.net?
Я хотел бы установить строку подключения программно, без каких-либо изменений в конфигурационных файлах / ключах реестра.
У меня есть этот кусок кода, но, к сожалению, это бросает исключение с "конфигурация только для чтения".
ConfigurationManager.ConnectionStrings.Clear();
string connectionString = "Server=myserver;Port=8080;Database=my_db;...";
ConnectionStringSettings connectionStringSettings =
new ConnectionStringSettings("MyConnectionStringKey", connectionString);
ConfigurationManager.ConnectionStrings.Add(connectionStringSettings);
Edit: Проблема в том, что у меня есть существующий код, который считывает строку подключения из конфигурации. Поэтому установка строки конфигурации вручную или через ресурс не кажется допустимыми параметрами. Что? Я действительно нужно, это способ изменения конфигурации программным способом.
8 ответов:
Я уже писал об этом в пост в моем блоге. Хитрость заключается в том, чтобы использовать отражение, чтобы совать значения в качестве способа получить доступ к непубличным полям (и методам).
например.
var settings = ConfigurationManager.ConnectionStrings[ 0 ]; var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic ); fi.SetValue(settings, false); settings.ConnectionString = "Data Source=Something";
Я искал ответ на тот же вопрос о том, чтобы разрешить пользователю изменять строку подключения в приложении click once, выбрав локальный 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)) }
другой способ приблизиться к этому - это работать с коллекцией напрямую:
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);
Я нахожу, что это работает для меня:
Configuration config = WebConfigurationManager.OpenWebConfiguration("~"); ConnectionStringsSection section = config.GetSection("connectionStrings") as ConnectionStringsSection; if (section != null) { section.ConnectionStrings["MyConnectionString"].ConnectionString = connectionString; config.Save(); }
Это перезаписывает существующую строку подключения.
в настоящее время я использую инъекцию зависимостей для обработки различных строк подключения в средах dev/prod и test. Мне все еще нужно вручную изменить webconfig, если я хочу перейти между dev и prod, но для тестирования у меня есть интерфейс IConnectionStringFactory с реализацией по умолчанию, которая смотрит на веб-конфигурацию и альтернативную конфигурацию тестирования, которая возвращает статические значения. Таким образом, когда я тестирую, я просто установить заводские испытания и будет верните строку тестового соединения для ключа, который я прошу. В противном случае он будет выглядеть в webconfig.
Я мог бы распространить это на другую реализацию для dev vs. prod, но мне более комфортно иметь одну реализацию IConnectionStringFactory в моей производственной сборке и реализацию тестирования в моей тестовой сборке.
вместо этого вы можете поместить его в файл ресурсов. Он не будет иметь встроенных функций класса ConfigurationManager, но он будет работать.
Предполагая Ресурсов.resx:
Resources.Default.ConnectionString = "Server=myserver;" // etc
тогда в вашем коде:
conn.ConnectionString = Resources.Default.ConnectionString
это хак, я знаю.
в дополнение к другим заданным ответам и предполагая, что строка подключения не является просто другой переменной конфигурации или константой в целом, вы можете рассмотреть возможность использования SqlConnectionStringBuilder класс вместо непосредственного объединения строки вместе.
EDIT: Ups, извините, просто увидел, что вы в основном хотите прочитать строку подключения (полный, я думаю) из другого источника.