Как мне настроить конфигурацию строки подключения в .net?

Я хотел бы установить строку подключения программно, без каких-либо изменений в конфигурационных файлах / разделах реестра.

У меня есть этот кусок кода, но, к сожалению, он выдает исключение «конфигурация доступна только для чтения».

ConfigurationManager.ConnectionStrings.Clear();
string connectionString = "Server=myserver;Port=8080;Database=my_db;...";
ConnectionStringSettings connectionStringSettings = 
  new ConnectionStringSettings("MyConnectionStringKey", connectionString);
ConfigurationManager.ConnectionStrings.Add(connectionStringSettings);

Изменить: проблема в том, что у меня есть существующий код, который читает строку подключения из конфигурации. Так что установка строки конфигурации вручную или через ресурс не выглядит как допустимые параметры. Что мне действительно нужно, так это способ изменить конфигурацию программно.

11.12.2008 16:44:53
Вы хотите изменить строку подключения в файле конфигурации? Легко динамически создать новое соединение с любой строкой соединения, которую вы строите ... если это то, что вы хотите сделать ... Но если вы хотите записать в фактический файл конфигурации, это другая проблема.
Charles Bretana 11.12.2008 16:50:38
9 ОТВЕТОВ
РЕШЕНИЕ

Я написал об этом в посте на моем блоге . Хитрость заключается в том, чтобы использовать отражение для определения значений в качестве способа получить доступ к закрытым полям (и методам).

например.

var settings = ConfigurationManager.ConnectionStrings[ 0 ];

var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic );

fi.SetValue(settings, false);

settings.ConnectionString = "Data Source=Something";
115
18.12.2008 11:29:00
Если вы используете NHibernate, посмотрите этот nhforge.org/wikis/howtonh/…
David Gardiner 4.05.2009 06:16:52
Спасибо, Дэвид. Отличный ответ, очень полезно!
βӔḺṪẶⱫŌŔ 25.05.2011 21:16:18
Отличное решение! Если вы хотите добавить новую строку подключения, используйте следующее для включения добавления в коллекцию ConnectionString:typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(ConfigurationManager.ConnectionStrings, false);
Allon Guralnek 3.10.2011 08:56:07
Есть что-то, что кажется неправильным в использовании отражения, чтобы изменить свойство на доступное для записи, но черт, оно работает!
Brian 5.05.2012 18:28:48
Этот материал необходим, поэтому я ненавижу .NET. @Simon_Weaver Не так в том смысле, что это не работает; как ... морально неправильно.
jpmc26 13.08.2016 03:06:57

Вместо этого вы можете поместить его в файл ресурсов. Он не будет иметь встроенных функций класса ConfigurationManager, но он будет работать.

Предполагая, что Resources.resx:

Resources.Default.ConnectionString = "Server=myserver;" // etc

Тогда в вашем коде:

conn.ConnectionString = Resources.Default.ConnectionString

Это хак, я знаю.

1
11.12.2008 16:50:49

ConfigurationManager используется для чтения из файла конфигурации.

Ваше решение состоит в том, чтобы просто установить conn.ConnectionString в нужную вам строку conn.

-2
11.12.2008 16:55:53

В настоящее время я использую внедрение зависимостей для обработки различных строк подключения в средах разработки и тестирования и тестирования. Мне все еще нужно вручную изменить webconfig, если я хочу перейти между dev и prod, но для тестирования у меня есть интерфейс IConnectionStringFactory с реализацией по умолчанию, которая просматривает веб-конфигурацию, и альтернативной конфигурацией тестирования, которая возвращает статические значения. Таким образом, когда я тестирую, я просто устанавливаю фабрику для реализации тестирования, и она возвращает строку подключения тестирования для ключа, который я запрашиваю. В противном случае это будет выглядеть в webconfig.

Я мог бы распространить это на другую реализацию для dev против prod, но мне удобнее иметь единственную реализацию IConnectionStringFactory в моей производственной сборке и реализацию тестирования в моей сборке тестирования.

5
11.12.2008 16:57:48

В дополнение к другим приведенным ответам и в предположении, что строка соединения не является просто другой конфигурационной переменной или константой в целом, вы можете рассмотреть возможность использования класса SqlConnectionStringBuilder вместо прямой конкатенации строки вместе.

РЕДАКТИРОВАТЬ: Ups, извините, только что увидел, что вы в основном хотите прочитать строку подключения (я думаю, завершено) из другого источника.

1
15.04.2019 16:57:13

Я считаю, что это работает для меня:

Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
ConnectionStringsSection section = config.GetSection("connectionStrings") as         ConnectionStringsSection;
if (section != null)
{
    section.ConnectionStrings["MyConnectionString"].ConnectionString = connectionString;
    config.Save();
}

Это перезаписывает существующую строку подключения.

7
21.08.2009 15:42:01
Будьте осторожны с изменением файла web.config, так как он вызывает перезапуск рабочего процесса. Я попытался установить Connectionstring для файловой базы данных в событии ApplicationStart, которое вызвало перезапуск приложения для каждой посещенной страницы ...
Thomas 12.02.2010 16:19:44
Верно. Я использовал это как функцию административного инструмента для шифрования и дешифрования файла web.config на учетной записи общего хостинга. Как отметил Томас, вы не захотите делать это как часть запуска сеанса или приложения.
Rebecca 14.02.2010 20:05:43
+1: это идеально подходит для моих целей (интеграционный тест). Однако, потому что мой производственный код использует, ConfigurationManagerя должен сделать, как ConfigurationManager.RefreshSection("connectionStrings");только я обновил раздел в моем тесте.
Alex Humphrey 20.07.2011 10:46:18
@AlexHumphrey Вы не должны этого делать, если вы используете Remove () и Add () вместо индексации и назначения. Я не проверял это, но все, что я знаю, это то, что я использую Clear () и Add (), и он прекрасно работает для меня.
Neo 8.11.2012 18:03:01
Это может работать в ASP.NET (я не совсем уверен), но это абсолютно не работает с любым исполняемым файлом, который не загружается автоматически (например, консольное приложение). Конфигурация уже загружена, прежде чем ее можно будет выполнить, то есть строка подключения никогда не изменяется.
jpmc26 13.08.2016 03:26:19

Я искал ответ на тот же вопрос о том, чтобы разрешить пользователю изменять строку подключения в приложении один раз, выбрав локальный 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))
}
8
17.04.2014 12:20:39
К вашему сведению, это приводит к перезагрузке домена вашего приложения, поэтому используйте его осторожно
yano 15.04.2014 01:22:08

Другим способом решения этой проблемы является непосредственное управление коллекцией:

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);
8
31.07.2014 15:41:12

Похоже, что имя изменилось с .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";
0
19.03.2019 19:46:16