Trasmitiendo las variables de aplicación entre capas en una solución .NET

(Y haciéndolas dinámicas)

Sea el escenario de una típica aplicación 3-tier para un sistema de información. Hay una capa de presentación, una de negocios y la de datos. En la capa de datos según lineamientos plenamente aceptados, tenemos las cadenas de conexión a las bases de datos que se usarán. Si la aplicación se desarrolla con el Framework 2.0, es normal que las capas de datos y negocio, queden representadas por DLLs que luego son consumidas por una aplicación Windows o web, por ejemplo. Entonces cada cliente se comunica con sus capas servidoras que tienen la conexión a base de datos y saben en dónde están los datos para operar.

Hasta ahí no hay ningún problema. Cuando la aplicación ya está lista para producción, generalmente se usará una base de datos distinta a la usada en desarrollo y quizá en pruebas.
Este cambio, gracias a la arquitectura del framework 2.0 en adelante, solo implicaría cambiar el archivo de configuración (App.config) de la DLL de capa de datos. Se abre con un editor de texto, y se edita el XML con la nueva cadena de conexión, y ya está. Todos los clientes quedan conectados a la nueva fuente. Pero qué sucede si se crea una aplicación de capas, que no necesariamente tiene la misma conexión de base de datos para todos los clientes? Cómo lograr que cada cliente genere una cadena de conexión dinámica que se pueda cambiar a discreción permitiendo que la aplicación funcione correctamente?

En el framework 2.0 las cadenas de conexión son tratadas como variables de alcance de aplicación. El otro tipo de alcance es de usuario. Cuando la variable es de alcance de usuario, esa misma, puede ser modificada en tiempo de ejecución. Entonces sería fácil crear métodos para que los clientes de presentación de alguna manera transmitieran los nuevos valores de las cadenas de conexión a las otras capas. No obstante, como mencioné anteriormente, las cadenas de conexión son de alcance "aplicación" y estas variables no se pueden modificar en tiempo de ejecución. Así que para un cliente es imposible modificarlas transmitiendo nuevos valores mientras está corriendo. Así que el método de crear código que transmita los cambios requeridos, no es factible. La solución, aunque es trivial, no es intuitiva y Visual Studio no provee una manera directa para lograrla. Para encontrarla y entender de qué se trata, suponga que llamamos a la cadena de conexión strCon1. Entonces, queda guardada dentro de los settings de la DLL de datos como strCon1 y tiene determinados valores de conexión.

Además permitiría cambiar la cadena de conexión dinámicamente, antes de iniciar la ejecución de la aplicación (recordemos que ésta es una variable de aplicación). Al distribuir la aplicación, se puede hacer con o sin el archivo de configuración de la aplicación. Si se distribuye sin este, cuál será entonces la cadena de conexión a usarse? Se usaría la última presente al compilar la librería (Esto gracias a la compilación del archivo de propiedades en la clase Settings.settings).

Como es conocido, cada capa en el framework, vendría representada por un assembly (DLL) por separado. Es decir, cada capa es un proyecto dentro de la solución y cada proyecto de estos, tiene sus propias propiedades y variables de usuario y aplicación. Como ya se mencionó estas variables van en archivos App.config. Al compilar la solución, dentro de cada carpeta de salida de los proyectos queda un archivo App.config para las dallas, y un archivo miaplicacion.exe.config para los ejecutables en el caso de aplicaciones Windows o web.config en el caso de web services o aplicaciones web ( en estos últimos dos casos, el archivo queda en el root del sitio web).

Lo que uno como desarrollador distribuiría, sería únicamente los compilados y salidas de los proyectos componentes de la solución. Entonces irían en nuestro ejemplo dos DLL (una de datos, la otra de negocio) y el ejecutable. Además irían los archivos de configuración, que en el caso de las DLL se llamarían igual.

Pero si se llaman igual, cómo se soluciona este problema? Fácil; basta con combinar los archivos de configuración en uno solo con el mismo nombre y listo. Pero es fundamental que los nombres de las variables (por ejemplo de cadenas de conexión) permanezcan invariables.

En mi búsqueda de esta solución, una de las cosas que intenté fue agregar una variable de aplicación a la capa de presentación, que tuviera el mismo nombre de conexión y los mismos parámetros que la definida en la capa de datos usando la interfaz de Visual Studio. De esta manera se produciría un miaplicacion.exe.config, con la cadena de conexión que usa la capa de datos y así cada vez que yo cambiase este archivo y reiniciase la aplicación, el sistema tomaría los cambios y funcionaría de acuerdo a ellos.
Al ver con más detalle el resultado, descubrí que el nombre de la variable no había quedado exactamente igual que el usado por la capa de datos. Y en la práctica, este hecho no es muy fácil de identificar.

Así que dado que uno puede estar tentado a agregar el setting usando la interfaz de Visual Studio, puede incurrir en este error si no se fija lo suficientemente bien. Lo mejor, es no agregar el setting de esta manera. Sino agregar a mano (o editar a mano si ya existe), un archivo App.config y escribir el setting exactamente como se usó en la capa de datos.Cuando así lo hice, con felicidad observé como finalmente los cambios en el archivo XML se veían reflejados en la aplicación, cuando esta empezaba a correr. Esto me dio la flexibilidad requerida para configurar cada cliente con una fuente de datos distinta a la usada en el desarrollo de la aplicación.

Conclusión: Para propagar las variables de configuración desde las capas más exteriores a las más interiores dentro de un sistema n-tier usando framework 2.0 en adelante, basta con escribirlas todas en el archivo de configuración de la capa más externa, de manera que sean absolutamente idénticas a las usadas en las capas internas. Y no es posible hacer esto, solo con la ayuda de la interfaz gráfica de Visual Studio, pues se requiere editar el archivo manualmente y luego incluirlo en el deployment de la aplicación.