¿Cómo configuro una cadena de conexión config programáticamente en .net?

Me gustaría establecer una cadena de conexión mediante progtwigción, sin ningún cambio en los archivos de configuración / claves de registro.

Tengo este fragmento de código, pero desafortunadamente arroja una excepción con “la configuración es de solo lectura”.

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

Editar: El problema es que tengo un código existente que lee la cadena de conexión de la configuración. Por lo tanto, configurar la cadena de configuración manualmente o mediante un recurso no parece una opción válida. Lo que realmente necesito es una forma de modificar la configuración mediante progtwigción.

He escrito sobre esto en una publicación en mi blog . El truco es usar la reflexión para introducir valores como una manera de obtener acceso a los campos no públicos (y métodos).

p.ej.

 var settings = ConfigurationManager.ConnectionStrings[ 0 ]; var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic ); fi.SetValue(settings, false); settings.ConnectionString = "Data Source=Something"; 

Estaba buscando la respuesta a la misma pregunta acerca de permitir al usuario modificar la cadena de conexión en una aplicación de un solo clic seleccionando un servidor SQL local.

El siguiente código muestra un formulario de usuario que contacta a todos los servidores SQL disponibles localmente y les permite seleccionar uno. A continuación, construye una cadena de conexión para ese servidor y la devuelve de una variable en el formulario. El código modifica los archivos de configuración Y LO GUARDEA.

 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)) } 

Otra forma de abordar esto sería operar directamente en la colección:

 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); 

Encuentro que esto funciona para mí:

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

Esto sobrescribe una cadena de conexión existente.

Actualmente estoy usando la dependency injection para manejar diferentes cadenas de conexión en entornos dev / prod vs. test. Todavía tengo que cambiar manualmente el webconfig si quiero moverme entre dev y prod, pero para probarlo tengo una interfaz IConnectionStringFactory con una implementación predeterminada que examina la configuración web y una configuración de prueba alternativa que devuelve valores estáticos. De esa manera, cuando estoy probando simplemente configuro la fábrica para la implementación de prueba y devolverá la cadena de conexión de prueba para la clave que solicito. De lo contrario, se verá en el webconfig.

Podría extender esto a otra implementación para dev vs. prod, pero me siento más cómodo con una única implementación de IConnectionStringFactory en mi ensamblaje de producción y la implementación de prueba en mi ensamblaje de prueba.

Podrías ponerlo en un archivo de recursos en su lugar. No tendrá las características incorporadas de la clase ConfigurationManager, pero funcionará.

Asumiendo Resources.resx:

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

Luego en tu código:

conn.ConnectionString = Resources.Default.ConnectionString

Es un truco, lo sé.

Además de las otras respuestas dadas, y suponiendo que la cadena de conexión no es simplemente otra variable de configuración o constante como un todo, puede considerar usar la clase SqlConnectionStringBuilder en lugar de concatenar directamente la cadena.

EDITAR: Ups, lo siento, acabo de ver que básicamente quieres leer tu cadena de conexión (completa, supongo) de otra fuente.

ConfigurationManager se usa para leer desde el archivo de configuración.

Su solución es simplemente establecer conn.ConnectionString en la cadena de conexión que necesita.