none
Duda sobre gestión de múltiples conexiones a la BD en aplicación web RRS feed

  • Pregunta

  • Buenos días, estoy intentando optimizar una de mis aplicaciones web y me he encontrado con bastantes problemas en cuanto a las conexiones a la base de datos.

    1.- He creado una clase que gestiona la conexión a la BD

    2.- He creado una clase en la que almaceno las funciones y procedimientos básicos para el funcionamiento de la aplicación.

    3.- He hecho que la clase de Funciones herede de la clase Conexiones para poder usar la misma conexión para dichas funciones

    4.- Por desgracia, muchas de estas funciones usan DataReaders y cuando se anidan varias funciones, al usar la misma conexión, me falla la aplicación.

    5.- Ahora se me ocurre que debo eliminar dicha herencia y crear/destruir una instancia a una conexión para cada función y así evitarme los errores con los DataReaders.

    Me da rabia, por que estoy trabajando para optimizar el código y eso de crear 50 conexiones me parece una mala práctica.

    Mi duda es, ¿esto es peligroso para el rendimiento?, ¿es una buena idea?, ¿hay alguna otra solución que no soy capaz de ver?

    Cualquier propuesta será de ayuda.

    Muchas gracias

    jueves, 17 de mayo de 2012 8:53

Respuestas

  • 2.- He creado una clase en la que almaceno las funciones y procedimientos básicos para el funcionamiento de la aplicación.

    3.- He hecho que la clase de Funciones herede de la clase Conexiones para poder usar la misma conexión para dichas funciones

    Desde el punto vista de base de datos, no hay ningún problema. Desde el punto de vista de Diseño Orientado a Objetos, lo que quieres hacer no tiene sentido. Si me permites darte un consejo a nivel de diseño (que no de base de datos), organiza tus clases de forma que cada una sirva para una sola cosa, o en el peor de los casos, unas pocas cosas muy relacionadas entre si.

    Cada clase debería ser funcionalmente independiente de otras clases. Idealmente, cada clase sólo debería depender de otras clases por las llamadas a sus miembros públicos. Como esto es difícil de conseguir en la práctica, es usual que en el diseño haya clases que contienen otras clases o colecciones de objetos de otras clases. 

    Entonces, volviendo a tu problema: crear 50 conexiones simultáneas no es una buena práctica. Una buena práctica es crear, abrir, usar, cerrar y destruir la conexión cada vez que la necesitas. Entonces, tu clase que gestiona las conexiones se encargará de entregarte objetos de tipo Connection ya inicializados. Esto es tan común que hasta tiene un nombre propio: se llama Object Factory. Tu clase que gestiona las conexiones es un Object Factory de conexiones.

    Meter toda la lógica de la aplicación en una sola clase es lo peor que puedes hacer. Primero, porque terminará siendo una clase inmensa. Segundo, porque cuando tengas que modificar algo, posiblemente otras partes de la clase se verán afectadas. Yo suelo usar un patrón de capas, donde cada capa se dedica a una sola cosa: una capa para acceso a datos, una capa para la representación del modelo de negocio y otra capa para la interfaz con el usuario. 

    Otros patrones aplicables a este tipo de aplicación son el Modelo-Vista-Controlador (donde el modelo a su vez integra lógica y persistencia de los datos; y la interfaz con el usuario se divide en vista y controlador); o el patrón Presentación-Abstracción-Control (donde organizas las entidades en forma de "agentes", cada una de los cuales tiene su propia interfaz, una capa de abstracción y una capa de control; y los agentes interactúan entre si) Puestos a elegir, para el tipo de aplicación que estás haciendo (web) es mejor 3-capas o MVC.

    ¿Eliminar la herencia? Sí, definitivamente; aunque la razón no tiene nada que ver con los fallos de conexión.

    ¿Te da rabia? Controla la rabia, no ayuda para nada. Haz un buen diseño e impleméntalo y verás que en vez de rabia vas a sentir satisfacción.

    ¿Es peligroso para el rendimiento? No. Es peligroso para casi todos los demás atributos de calidad del software, pero no para el rendimiento.

    ¿Hay otra solución? Sí, hay montones de soluciones. Te acabo de proponer tres soluciones arquitecturales: 3-capas; MVC y PAC.

    Saludos,

    Y.


    logo osoft
    Si he contestado tu pregunta, por favor marca mi post como respuesta.
    ...Y si mi post te ha servido, márcalo como útil smile

    • Marcado como respuesta elBaco jueves, 17 de mayo de 2012 10:24
    jueves, 17 de mayo de 2012 9:26
  • Hola, 

    el propio .NET ya optimiza las conexiones con las base de datos. Tienes una lectura interesante aquí

    http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

    Respecto a abrir conexiones, aunque tu abras 50 veces la conexión a la base de datos puede que realmente solo este abierta una conexión. De esto se encarga el propio .NET.

    El tema de los DataReader, es que por defecto solo se admite un tipo de conexión de "este tipo" por conexión. Esto es por defecto, y si usas Sql Server 2005 o superior puede modificar esté parámetro en tu configuración

    http://msdn.microsoft.com/en-us/library/h32h3abf.aspx

    O sea, añade esto

    MultipleActiveResultSets=True

    a tu cadena de conexión.


    Atentamente, Sergio.

    Blog
    Twitter

    • Marcado como respuesta elBaco jueves, 17 de mayo de 2012 10:24
    jueves, 17 de mayo de 2012 9:28

Todas las respuestas

  • 2.- He creado una clase en la que almaceno las funciones y procedimientos básicos para el funcionamiento de la aplicación.

    3.- He hecho que la clase de Funciones herede de la clase Conexiones para poder usar la misma conexión para dichas funciones

    Desde el punto vista de base de datos, no hay ningún problema. Desde el punto de vista de Diseño Orientado a Objetos, lo que quieres hacer no tiene sentido. Si me permites darte un consejo a nivel de diseño (que no de base de datos), organiza tus clases de forma que cada una sirva para una sola cosa, o en el peor de los casos, unas pocas cosas muy relacionadas entre si.

    Cada clase debería ser funcionalmente independiente de otras clases. Idealmente, cada clase sólo debería depender de otras clases por las llamadas a sus miembros públicos. Como esto es difícil de conseguir en la práctica, es usual que en el diseño haya clases que contienen otras clases o colecciones de objetos de otras clases. 

    Entonces, volviendo a tu problema: crear 50 conexiones simultáneas no es una buena práctica. Una buena práctica es crear, abrir, usar, cerrar y destruir la conexión cada vez que la necesitas. Entonces, tu clase que gestiona las conexiones se encargará de entregarte objetos de tipo Connection ya inicializados. Esto es tan común que hasta tiene un nombre propio: se llama Object Factory. Tu clase que gestiona las conexiones es un Object Factory de conexiones.

    Meter toda la lógica de la aplicación en una sola clase es lo peor que puedes hacer. Primero, porque terminará siendo una clase inmensa. Segundo, porque cuando tengas que modificar algo, posiblemente otras partes de la clase se verán afectadas. Yo suelo usar un patrón de capas, donde cada capa se dedica a una sola cosa: una capa para acceso a datos, una capa para la representación del modelo de negocio y otra capa para la interfaz con el usuario. 

    Otros patrones aplicables a este tipo de aplicación son el Modelo-Vista-Controlador (donde el modelo a su vez integra lógica y persistencia de los datos; y la interfaz con el usuario se divide en vista y controlador); o el patrón Presentación-Abstracción-Control (donde organizas las entidades en forma de "agentes", cada una de los cuales tiene su propia interfaz, una capa de abstracción y una capa de control; y los agentes interactúan entre si) Puestos a elegir, para el tipo de aplicación que estás haciendo (web) es mejor 3-capas o MVC.

    ¿Eliminar la herencia? Sí, definitivamente; aunque la razón no tiene nada que ver con los fallos de conexión.

    ¿Te da rabia? Controla la rabia, no ayuda para nada. Haz un buen diseño e impleméntalo y verás que en vez de rabia vas a sentir satisfacción.

    ¿Es peligroso para el rendimiento? No. Es peligroso para casi todos los demás atributos de calidad del software, pero no para el rendimiento.

    ¿Hay otra solución? Sí, hay montones de soluciones. Te acabo de proponer tres soluciones arquitecturales: 3-capas; MVC y PAC.

    Saludos,

    Y.


    logo osoft
    Si he contestado tu pregunta, por favor marca mi post como respuesta.
    ...Y si mi post te ha servido, márcalo como útil smile

    • Marcado como respuesta elBaco jueves, 17 de mayo de 2012 10:24
    jueves, 17 de mayo de 2012 9:26
  • Hola, 

    el propio .NET ya optimiza las conexiones con las base de datos. Tienes una lectura interesante aquí

    http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

    Respecto a abrir conexiones, aunque tu abras 50 veces la conexión a la base de datos puede que realmente solo este abierta una conexión. De esto se encarga el propio .NET.

    El tema de los DataReader, es que por defecto solo se admite un tipo de conexión de "este tipo" por conexión. Esto es por defecto, y si usas Sql Server 2005 o superior puede modificar esté parámetro en tu configuración

    http://msdn.microsoft.com/en-us/library/h32h3abf.aspx

    O sea, añade esto

    MultipleActiveResultSets=True

    a tu cadena de conexión.


    Atentamente, Sergio.

    Blog
    Twitter

    • Marcado como respuesta elBaco jueves, 17 de mayo de 2012 10:24
    jueves, 17 de mayo de 2012 9:28