obtener net from connectionstring asp app .net asp.net linq-to-sql configuration connection-string

.net - net - obtener connectionstring web config



Cadena de conexión infernal en.NET/LINQ-SQL/ASP.NET (13)

¿Qué hay de la definición de un objeto ConnectionFactory, que toma una enumeración como parámetro y devuelve un objeto de conexión completamente formado?

Tengo una aplicación web que comprende lo siguiente:

  • Un proyecto web (con un archivo web.config que contiene una cadena de conexión, pero no un código de acceso a datos en el proyecto web)
  • Un proyecto de acceso a datos que utiliza clases LINQ-SQL para proporcionar entidades a la IU del proyecto web (este proyecto tiene un archivo de configuración y un app.config, ambos con cadenas de conexión)

Cuando construyo y despliego, no hay ningún archivo de configuración o app.config en el directorio Bin con el .dll de acceso a datos, pero cambiar la cadena de conexión en el archivo web.config no cambia la base de datos en consecuencia, por lo que la cadena de conexión debe compilarse en el dll de acceso a datos.

Lo que necesito es un archivo de configuración para toda mi implementación: sitio web, dlls de acceso a datos, todo, que tiene una cadena de conexión que se usa. Por el momento, parece haber varias cadenas de conexión que se usan o se codifican en todas partes.

¿Cómo puedo resolver este desastre?

Gracias por cualquier ayuda.


Aquí hay una manera de verlo. ¿Qué componente debería tomar la decisión sobre qué base de datos usar? Es posible que la base de datos (o al menos la cadena de conexión) pueda cambiar en el futuro. ¿El sitio web decide qué base de datos usar? O, ¿decide el DAL?

Si tiene bases de datos dev, QA, UAT y prod, la gestión de estas cadenas de conexión es crucial.

Si el sitio web decide, debe pasar la cadena de conexión de su web.config a DAL. Si se supone que el sitio web no debe saber ni importar de dónde provienen los datos, entonces la cadena de conexión pertenece al DAL.


El archivo de configuración para el proyecto de inicio definirá la configuración de todos los proyectos incluidos. Por ejemplo, si su proyecto web es el proyecto de inicio, cualquier referencia a "appSettings" buscará configuraciones desde web.config, esto incluye cualquier referencia a "appSettings" de su proyecto de acceso a datos. Por lo tanto, copie las configuraciones de configuración del app.config del proyecto de acceso a datos al web.config del proyecto web.


En un mundo perfecto, creo que podrías refactorizar tu capa de datos para recoger configuraciones a través de System.Configuration o constructores / fábricas relevantes. Lo que significa que necesita volver a cablear su fuente de configuración implícita o establecer conexiones explícitamente desde su host / consumidor. Otro patrón relacionado para centralizar estos tipos de constantes es arrojar una propiedad readonly en una clase helper estática y hacer que esa clase administre la resolución real de las configuraciones, etc.

Un lugar donde puede mirar que creo que muestra buenos ejemplos de cómo hacerlo de forma elegante es NHibernate y su gestión de configuración / mapeos. De acuerdo, es un poco de xml hell, y Fluent NHib es más azucarado, pero la mayoría de las muestras del mundo real le mostrarán cómo conciliar la configuración de un ensamblaje de soporte con el ensamblaje en ejecución.


Gracias por las respuestas.

Aquellos de ustedes que dicen que la aplicación usará la configuración en el web.config son correctos para las instancias en las que hago referencia en mi propio código:

_connectionString = ConfigurationManager.AppSettings["ConnectionString"];

... pero hay un problema diferente con los contextos de datos LINQ-SQL: creo que incluyen cadenas de conexiones en el dll compilado para usar en el constructor sin parámetros. Como dice tvanofosson, necesito crear contextos de datos pasando una referencia a la cadena de conexión en web.config. Que es donde me estaba metiendo en un enredo :)


También podría hacer que la aplicación web proporcione la cadena de conexión cuando necesite usar el proyecto de acceso a datos. Podrías hacerlo parte del constructor.

Además, podría escribir su propia lógica para cargar una cadena de conexión desde un archivo externo cuando el proyecto de acceso a datos realice sus llamadas.


Tira tu propia ConnectionFactory basada en archivos .config:

  • Definir una sección de configuración personalizada para correlacionar pares de clave / conexión
  • Enséñele a ConnectionFactory a buscar en esa sección de configuración usando nombre de host o nombre de máquina según corresponda
  • Complete los valores de clave / conexión de sus diversos servidores dev / qa / prod, y colóquelos en sus diversos archivos app.config, web.config, etc.

Pro:

  • Todo vive dentro del proyecto, así que no hay sorpresas
  • Agregar un destino de despliegue adicional es una operación de copiar / pegar en un archivo .config

Estafa:

  • Crea grandes secciones XML feas, especialmente si tienes una docena de servidores de producción
  • Necesita ser duplicado entre proyectos
  • Necesita cambio de código y volver a implementar para agregar un nuevo objetivo
  • El código necesita saber sobre el entorno en el que vivirá

Tuve un poco de lucha con este problema también. Encontré una solución usando la definición de clase parcial c # y ampliando el contexto de datos creado por dbml designer. Esta solución es bastante similar a la respuesta de tvanfosson. Lo que tiene que hacer es crear una clase de contexto de datos parcial con el constructor predeterminado que obtiene ConnectionString de la configuración y en las propiedades de DC del diseñador de dbml establecer la conexión a Ninguno. De esa manera, la cadena de conexión no se compilará en dll. Datacontext obtendrá automáticamente la cadena de conexión de la configuración de la conexión web.config connectionstring. No he probado si esto funciona con app.config también, pero creo que debería funcionar bien.

Aquí hay una muestra de clase DC parcial:

namespace MyApplication { /// <summary> /// Summary description for MyDataContext /// </summary> /// public partial class MyDataContext { public MyDataContext() : base(global::System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString, mappingSource) { OnCreated(); } } }


Su aplicación solo usará las entradas de configuración en el archivo web.config. Puede poner la configuración de configuración dll en el archivo web.config siempre que esté estructurada correctamente. Mi ejemplo es específico de VB usando My Namespace, pero te da la idea general.

En configSections paret del archivo de configuración necesitará una entrada:

<configSections> <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <section name="YourAssembly.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </sectionGroup></configSections>

Luego, en la parte applicationSettings del archivo de configuración, coloca las entradas para cada dll:

<applicationSettings> <YourAssembly.My.MySettings> <setting name="DebugMode" serializeAs="String"> <value>False</value> </setting> </YourAssembly.My.MySettings> </applicationSettings>


Para mantenerlo a salvo de cualquier cosa en el código generado automáticamente, anule la información de conexión en el método OnCreated () del contexto de datos:

using System.Configuration; namespace MyApplication { partial void OnCreated() { // attempt to use named connection string from the calling config file var conn = ConfigurationManager.ConnectionStrings["MyConnectionString"]; if (conn != null) Connection.ConnectionString = conn.ConnectionString; } }

De esta forma, el diseñador de dbml puede hacer las cosas de la conexión a su manera (lo cual no es agradable fuera de un proyecto web), pero usted toma el control final de la conexión cuando se ejecuta la aplicación.


Sé que esto es viejo, pero así es como lo hago (me gusta mucho el estilo de @ Seba pero no lo he intentado)

Esto supone que su archivo DBML reside en su propia biblioteca de clases, que he encontrado más conveniente cuando comparto entidades y acceso a datos en múltiples sitios web y otras bibliotecas de clases. También asume que ha nombrado la cadena de conexión igual en cada proyecto. Uso NAnt para configurar esto cuando implemento en diferentes entornos.

Basé esto en la respuesta superior de @tvanfosson - felicitaciones a ese tipo.

  1. Crea tu propia clase base, que se deriva de LinqDataContext

Aquí está el código VB:

Imports System.Configuration Public Class CustomDataContextBase Inherits System.Data.Linq.DataContext Implements IDisposable Private Shared overrideConnectionString As String Public Shared ReadOnly Property CustomConnectionString As String Get If String.IsNullOrEmpty(overrideConnectionString) Then overrideConnectionString = ConfigurationManager.ConnectionStrings("MyAppConnectionString").ConnectionString End If Return overrideConnectionString End Get End Property Public Sub New() MyBase.New(CustomConnectionString) End Sub Public Sub New(ByVal connectionString As String) MyBase.New(CustomConnectionString) End Sub Public Sub New(ByVal connectionString As String, ByVal mappingSource As System.Data.Linq.Mapping.MappingSource) MyBase.New(CustomConnectionString, mappingSource) End Sub Public Sub New(ByVal connection As IDbConnection, ByVal mappingSource As System.Data.Linq.Mapping.MappingSource) MyBase.New(CustomConnectionString, mappingSource) End Sub End Class

  1. Abra su archivo DBML y, en Propiedades, agregue el nombre de clase anterior a la propiedad de Clase base.

Tenga en cuenta que si colocó la clase de contexto de datos personalizada en el mismo conjunto, simplemente incluya el nombre de la clase, por ejemplo, CustomDataContext.

Si están en ensamblajes diferentes, use el nombre completamente calificado, por ejemplo, MyCo.MyApp.Data.CustomDataContext

  1. Para asegurarse de que las cosas de Designer funcionen correctamente, copie su cadena de conexión en el archivo app.config para la biblioteca de clases. Esto no se usará aparte en el IDE.

Eso es.

Deberá nombrar su cadena de conexión del mismo modo

Lo que básicamente está haciendo es forzar al contexto de datos a ignorar la información de conexión establecida en el archivo DBML. El uso de los métodos de ConfigurationManager significará que recogerá la cadena de conexión del conjunto que realiza la llamada.

HTH


Nunca he tenido un problema con la capa de acceso a datos (DAL) al poder usar las cadenas de conexión de mi archivo web.config . Por lo general, solo copio la sección de cadenas de conexión de DAL y la web.config en web.config . Estoy usando el diseñador de DBML para crear el contexto de datos.

Si esto no funciona para usted, puede especificar la cadena de conexión en el constructor de contexto de datos. En su proyecto web, tenga una clase estática que cargue su configuración, incluidas sus cadenas de conexión, y cuando cree su objeto DAL (o contexto de datos, si lo está creando directamente) simplemente páselo al constructor.

public static class GlobalSettings { private static string dalConnectionString; public static string DALConnectionString { get { if (dalConnectionString == null) { dalConnectionString = WebConfigurationManager .ConnectionStrings["DALConnectionString"] .ConnectionString; } return dalConnectionString; } } } ... using (var context = new DALDataContext(GlobalSettings.DALConnectionString)) { ... }


Tira tu propia ConnectionFactory basada en el Registro:

  • agregue una clave de registro para su aplicación en SOFTWARE / [YOUR_COMPANY] / [YOUR_APP]
  • agregue un valor de cadena para ConnectionString
  • Enseñe a su ConnectionFactory a descifrar la clave de registro adecuada (en un constructor estático, ¡no en todas las páginas cargadas!).
  • Exporte la información de registro como un archivo .reg, agréguelo al control de origen, modifíquelo y aplíquelo según sea necesario para configurar máquinas adicionales.

Pro:

  • Simple de configurar
  • Connectionstring vive en un solo lugar
  • No en web / app.config, por lo que no es necesario codificar las configuraciones específicas del entorno.
  • No en web / app.config, por lo que Junior Dev Jimmy no puede decirle accidentalmente a su servidor de producción que mire la base de datos DEV

Estafa:

  • No es inmediatamente obvio que las cosas importantes están viviendo en el registro, por lo que los nuevos desarrolladores necesitarán instrucciones.
  • Paso adicional al configurar una nueva máquina de despliegue
  • El registro es oldskool. Los desarrolladores Junior se burlarán de ti.