none
Duda sobre objeto conexión en Aplicación en Capas RRS feed

  • Pregunta

  • Hola a todos.

    Estoy desarrollando una aplicación C# (ADO Conectado) con arquitectura en 3 capas para la administración de un colegio. Es una de mis primeros sistemas en capas y tengo una duda...

    Antes les cuento como están organizadas las clases...

    -Capa de Presentación

    -Proyecto Windows Forms

    -Capa de Negocio, formada por:

    - Proyecto Negocio: Donde están las clases controladoras de las entidades

    - Proyecto Entidades (Capa transversal): Donde están las clases entidad del sistema (Sólo entidades)

    -Capa de Datos 

    - Proyecto Datos: Donde están las clases controladores de las entidades en lo que respecta al acceso a la BD.

    ¿Cual sería la mejor forma de manejar los objetos de conexión?

    Mi pregunta tal vez es amplia pero necesito opiniones al respecto ya que se me ocurren muchas formas pero no me queda claro cual sería la forma optima.

    Suponiendo que en la capa DATOS tengo una clase ControlDeAlumnos...

    ¿En cada método de datos instancio un objeto conexión distinto?

    ¿Creo una conexión a nivel de clase para que todos los métodos usen el mismo objeto?

    ¿Creo una clase conexión exponiendo como miembro el objconexión en la capa DATOS y hago que la clase ControlDeAlumnos herede de ella para poder acceder a sus miembros?

    Como ven no me queda claro...Como harían ustedes?

    Gracias


    miércoles, 18 de marzo de 2015 2:18

Todas las respuestas

  • Hola,

    La capa de datos es la responsable de proveer de información a las capas superiores y de ejecutar sentencias contra la base de datos según "ordenes"de las capas superiores. No es una buena estrategia tener la conexión abierta en tanto la aplicación este en uso, el tiempo de vida de la conexión debe de ser el mismo tiempo que utilices para obtener datos o para ejecutar alguna operación en la base de datos. Por ejemplo tengo un método que inserta clientes:

    public static Cliente cliente(Cliente cliente)
    {
      using (SqlConnection cn = new SqlConnection("CADENA_CONEXION"))
      {
        using (SqlCommand com = new SqlCommand("InsertarCliente", cn))
        {
          com.CommandType = CommandType.StoredProcedure;
    
          com.Parameters.AddWithValue("@Nombre", cliente.Nombre);
          com.Parameters.AddWithValue("@Edad", clientes.Edad);
    
          cn.Open();
    
          com.ExecuteNonQuery();
    
          return cliente;
        }
      }
    }

    La instrucción using define un ámbito al final del cual el objeto se destruye.

    Si la solución propuesta atendió su consulta no olvide marcarla como respuesta.


    Willams Morales
    Arequipa - PERÚ

    miércoles, 18 de marzo de 2015 3:28
  • Hola:

     Coincido con Willams, le objeto de conexión no debería de permanecer mucho tiempo abierta, y no te preocupes tanto de que cada método tenga que llamar a una nueva conexión, no siempre .Net tiene que abrir una nueva conexión por cada petición que le hagas a la Bd, .Net cuenta con un pool de conexiones que no se destruyen inmediatamente permitiéndote reusar una previamente ya creada.

     Para el caso que estas tratando quizás este articulo te brinde alguna orientación:

    Programación en 3 capas

    Analiza la capa de Acceso a Datos


    Saludos desde Monterrey, Nuevo León, México!!!

    miércoles, 18 de marzo de 2015 15:45
  • Gracias a William y Jose Luis por responder!

    William voy a tener en cuenta el uso de using, hasta ahora nunca lo usaba, me parece muy práctico.

    Me gustó mucho el artículo de José Luis. Me ha costado mucho encontrar artículos de nivel básico sobre sistemas de arquitecturas en capas. Me gusta porque se explica desde cero. En general en la web hay libros y pdfs sobre arquitecturas en capas pero aplicado a sistemas grandes y mas que nada parecen solo recomendaciones para aquellos que ya trabajan en estos sistemas.

    Y los pocos artículos que encontré sobre sistemas básicos trabajan de manera distinta (tal vez incorrecta) y no de la manera que yo conozco, por ejemplo en algunos casos los métodos de negocio o datos se incluyen dentro de la misma clase de entidad, en otros casos usan DataTables en lugar de listas, etc.

    Si es posible, necesitaría tener un ejemplo completo de un método tipo InsertarCliente usando using como el que presentó Williams pero incluyendo manejo de excepciones (try-catch).

    Y una pregunta más:

    -Los métodos CRUD de la capa Datos conviene hacerlos estáticos o de instancia?

    Gracias por compartir sus conocimientos.

    viernes, 20 de marzo de 2015 14:36
  • Hola:

    Si es posible, necesitaría tener un ejemplo completo de un método tipo InsertarCliente usando using

     En el articulo podras encontrar un ejemplo claro sobre como hacer los inserts:

            public void Insert(EProducto producto)
            {
                //Creamos nuestro objeto de conexion usando nuestro archivo de configuraciones
                using (SqlCeConnection cnx = new SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString()))
                {
                    cnx.Open();
                    //Declaramos nuestra consulta de Acción Sql parametrizada
                    const string sqlQuery =
                        "INSERT INTO Producto (Descripcion, Marca, Precio) VALUES (@descripcion, @marca, @precio)";
                    using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery, cnx))
                    {
                        //El primero de los cambios significativos con respecto al ejemplo descargado es que aqui...
                        //ya no leeremos controles sino usaremos las propiedades del Objeto EProducto de nuestra capa
                        //de entidades...
                        cmd.Parameters.AddWithValue("@descripcion", producto.Descripcion);
                        cmd.Parameters.AddWithValue("@marca", producto.Marca);
                        cmd.Parameters.AddWithValue("@precio", producto.Precio);
    
                        cmd.ExecuteNonQuery();
                    }
                }
            }
     Los métodos CRUD o mejor dicho las clases Staticas se conservan en memoria mientras que las instanciadas se destruyen después de usarlas...yo normalmente las prefiero instanciadas para llamarlas solo cuando las requiero..


    Saludos desde Monterrey, Nuevo León, México!!!

    viernes, 20 de marzo de 2015 15:36
  • Hola José Luis,

    Mencionas que usas clases de instancia, pero, por ejemplo tu método Insert, ¿tiene algún objetivo crear una instancia para la clase que lo contiene por cada vez que hagas uso de él?. Tu método Insert tiene algún campo o propiedad que requiera mantener un valor distinto por cada llamada que se haga? yo veo que ninguno. Pienso que estos métodos "ejecutores" deberían estar en clases estáticas, más aún, cuando los objetos que usas son destruidos (using).

    ¿quizá hay algo que yo no este tomando en cuenta?



    viernes, 20 de marzo de 2015 15:45
  • Hola:

     Realmente el método no es la que se instancia (nunca he logrado instanciar un método), de ahí mi aclaración "o mejor dicho las clases Staticas" posiblemente esta parte es la que te provoca la confusión...


    Saludos desde Monterrey, Nuevo León, México!!!

    viernes, 20 de marzo de 2015 15:49
  • Hola:

     Realmente el método no es la que se instancia (nunca he logrado instanciar un método), de ahí mi aclaración "o mejor dicho las clases Staticas" posiblemente esta parte es la que te provoca la confusión...


    Saludos desde Monterrey, Nuevo León, México!!!

    Hola José Luis,

    Gracias por la aclaración, modifique mi comentario anterior, te agradeceré tus comentarios o sustentos, que de hecho ayudará a mejorar o profundizar nuestros conocimientos.

    viernes, 20 de marzo de 2015 15:52
  • Hola:

     Willams; creo que están malinterpretando mi comentario.

     Los métodos contenidos en la clase que funge como DataAccess en el ejemplo mencionado, solo se instancia una vez, a nivel de clase (la clase que la va a utilizar) la clase DA contiene diferentes métodos capaces de realizar las tareas propias de acceso, lectura o escritura de la BD...entonces si se instancia una sola vez no veo inconveniente alguno...

     Ahora, me gustaría aprender a mi del porque usar una clase estática es mejor que una clase instanciada?.


    Saludos desde Monterrey, Nuevo León, México!!!

    viernes, 20 de marzo de 2015 16:07
  • Jose Luis: Volviendo a mi pregunta anterior, ya había visto el ejemplo que tenes en tu articulo, pero en mi pregunta pedía "Un ejemplo ... que incluya manejo de excepciones", lo que me gustaría ver es donde colocarías el bloque try-catch-finally.  Algo que en tu ejemplo no veo.

    Me adhiero a la pregunta sobre que conviene usar Clases estáticas o de instancias para la DAL.

    Saludos y gracias!

    viernes, 20 de marzo de 2015 16:36
  • Muchos éxitos compañero

    básicamente la capa datos deberia hacer

    Listar, Guardar, Eliminar, y actualizar

    La información de tus entidades YA PROCESADAS

    El corazón a mi entender es la capa de negocios ahi es donde se debe centrar toda tu atención

    Ejemplo de negocio de un insert

    class LogicaClientes
    ....
    bool Guardar(Cliente c)
    {
     int result = DatosClientes.Guardar(c);
     return result == 1;
    }
    
    ....

    La clase datos solamente debería realizar la conexión insertar el o los registros devolver success o no

    listo

    Es bueno mantener la separacion de clases a nivel de datos dado que puede que la base de datos de los clientes sea distinta a otras manejadas por la app

    saludos

     

    G. Poliovei

    viernes, 20 de marzo de 2015 16:45
  • Muchos éxitos compañero

    básicamente la capa datos deberia hacer

    Listar, Guardar, Eliminar, y actualizar

    La información de tus entidades YA PROCESADAS

    El corazón a mi entender es la capa de negocios ahi es donde se debe centrar toda tu atención

    Ejemplo de negocio de un insert

    class LogicaClientes
    ....
    bool Guardar(Cliente c)
    {
     int result = DatosClientes.Guardar(c);
     return result == 1;
    }
    
    ....

    La clase datos solamente debería realizar la conexión insertar el o los registros devolver success o no

    listo

    Es bueno mantener la separacion de clases a nivel de datos dado que puede que la base de datos de los clientes sea distinta a otras manejadas por la app

    saludos

     

    G. Poliovei

    viernes, 20 de marzo de 2015 16:49
  • Hola Carlos:

    Jose Luis: Volviendo a mi pregunta anterior, ya había visto el ejemplo que tenes en tu articulo, pero en mi pregunta pedía "Un ejemplo ... que incluya manejo de excepciones", lo que me gustaría ver es donde colocarías el bloque try-catch-finally.  Algo que en tu ejemplo no veo.

     Creo que tienes toda la razón, volvamos a tu caso.

     En la capa de Datos no uso el Try Catch porque simplemente no serviría de nada atrapar alguna excepción en ese punto, si analizas el ejemplo detenidamente te daras cuenta el uso del TryCatch esta en la clase que representa la Presentación:

            private void Guardar()
            {
                try
                {
                    if (_producto == null) _producto = new EProducto();
    
                    _producto.Id = Convert.ToInt32(txtId.Text);
                    _producto.Descripcion = txtDescripcion.Text;
                    _producto.Marca = txtMarca.Text;
                    _producto.Precio = Convert.ToDecimal(txtPrecio.Text);
    
                    _productoBol.Registrar(_producto);
    
                    if (_productoBol.stringBuilder.Length != 0)
                    {
                        MessageBox.Show(_productoBol.stringBuilder.ToString(), "Para continuar:");
                    }
                    else
                    {
                        MessageBox.Show("Producto registrado/actualizado con éxito");
    
                        TraerTodos();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format("Error: {0}", ex.Message), "Error inesperado");
                }
            }

     Esto para atrapar en presentación cualquier excepción que pudiera ocurrir ya sea desde la capa de Acceso a Datos o desde la Lógica de negocio.

     Bien, en este ejemplo no se centra totalmente en el manejo de excepciones porque si ocurre alguna en la capa de acceso a datos los detalles técnicos se irían hasta presentación y se le mostraría al usuario detalles técnicos de lo ocurrido.

     En desarrollos personales, uso el TryCatch en la capa de Negocio, para atrapar los detalles técnicos y enviar a presentación algún mensaje mas compresible, enviando el detalle técnico a algún Log para posteriormente analizar este log...


    Saludos desde Monterrey, Nuevo León, México!!!

    viernes, 20 de marzo de 2015 16:59
  • Hola José luis,

    La aclaración que hago es para dar respuesta a la duda que tiene el OP respecto a usar métodos estáticos o de instancia.

    Tu nos comentaste que preferías usar clases de instancia, yo pregunte por tu sustento, finalmente no me queda claro el porque prefieres no usar métodos estáticos. Intentaré, darte mi sustento, pero quiero dejar claro que no creo tener la verdad absoluta, de hecho, el objetivo de este foro es cotejar opiniones y aprender de ello.

    La diferencia entre una clase estática y una clase de instancia es básicamente que de una clase estática no se puede crear instancias y tampoco invocar sus constructores. Ahora, uno de los criterios para definir una clase de instancia es porque podríamos requerir obtener o establecer valores para las propiedades y campos internos para la instancia, pero en el caso de los métodos que sólo ejecutan una acción y cuyos valores se pasan a través de parámetros de su propia firma no considero necesario crear una clase de instancia, ¿para qué? ¿bajo que objetivo?. Los métodos de persistencia, realizan una acción y nada más.

    Una de las "desventajas" de las clases estáticas es que "viven y no se destruyen"  posterior a ser llamadas, pero si te das cuenta, los métodos de persistencia no tienen variables u objetos que se puedan quedar en memoria, porque como se sugiere el uso de using, este hace que terminado el ámbito se destruya el objeto. Reitero que sólo para el caso puntual del ejemplo, porque podría existir la necesidad de ejecutar pruebas y quizá para ello si se requiera crear clases de instancia.

    Quedo a la espera de observaciones que tengan respecto a mis comentarios, que como repito apoyarán a que el OP tenga claro el camino a tomar.

    viernes, 20 de marzo de 2015 17:13
  • Hola Willams:

     Agradezco tu aporte.

     Pero no estoy en contra de usar clases estáticas como creo que me estas entendiendo, eso dependerá de lo que se desee hacer con los valores contenidos en los métodos.

     Para el caso en especifico de Carlos, yo uso siempre clases instanciadas, sera por costumbre, sera por mayor tranquilidad, pero las prefiero así, porque tampoco he visto ventaja de usar una clase estática si no necesito conservar los resultados de los métodos si solo voy a pasar valores para que una clase estática...es mi apreciación de las cosas.


    Saludos desde Monterrey, Nuevo León, México!!!

    viernes, 20 de marzo de 2015 17:40
  • Muchas gracias a todos por las respuestas me han aclarado bastante el tema!
    domingo, 22 de marzo de 2015 3:32