Как установить конфигурацию строки подключения программно 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 58

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, извините, просто увидел, что вы в основном хотите прочитать строку подключения (полный, я думаю) из другого источника.

ConfigurationManager используется для читать из файла config.

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