Как программно установить конфигурацию строки подключения в .net? - PullRequest
58 голосов
/ 11 декабря 2008

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

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

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

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

Ответы [ 9 ]

113 голосов
/ 18 декабря 2008

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

например.

var settings = ConfigurationManager.ConnectionStrings[ 0 ];

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

fi.SetValue(settings, false);

settings.ConnectionString = "Data Source=Something";
8 голосов
/ 31 июля 2014

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

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 голосов
/ 20 сентября 2011

Я искал ответ на тот же вопрос о том, чтобы разрешить пользователю изменять строку подключения в приложении с однократным нажатием, выбрав локальный 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))
}
7 голосов
/ 21 августа 2009

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

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

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

5 голосов
/ 11 декабря 2008

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

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

1 голос
/ 12 декабря 2008

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

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

1 голос
/ 11 декабря 2008

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

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

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

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

conn.ConnectionString = Resources.Default.ConnectionString

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

0 голосов
/ 19 марта 2019

Похоже, что имя изменилось с .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 голосов
/ 11 декабря 2008

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

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

...