Desarrollo de Aplicaciones N-Capas


El desarrollo de una aplicación N-Capas es básicamente un estilo de programación en el cual se separan lógicamente cada uno de los elementos de la aplicación, esto es, cada una de las capas en la que estará formada nuestra aplicación.

Este es nuestro diagrama de base de datos.

Estos son los procedimientos utilizados.

USE Tienda
GO

CREATE PROCEDURE ListarCategorias
AS
SELECT IdCategoria [Id],
	ISNULL(CodigoCategoria,'') [Codigo],
	ISNULL(Nombre,'')[Nombre],
	ISNULL(Observacion,'')[Observacion]
FROM Categoria
GO

CREATE PROCEDURE TraerCategoriaPorId
@ID int
AS
SELECT IdCategoria [Id],
	ISNULL(CodigoCategoria,'') [Codigo],
	ISNULL(Nombre,'')[Nombre],
	ISNULL(Observacion,'')[Observacion]
FROM Categoria
WHERE IdCategoria = @ID
GO

CREATE PROCEDURE InsertarCategoria
	@CODIGO VARCHAR(8),
	@NOMBRE VARCHAR(100),
	@OBSERVACION TEXT
AS
INSERT INTO Categoria(CodigoCategoria,Nombre,Observacion)
VALUES(@CODIGO,@NOMBRE,@OBSERVACION)
GO

CREATE PROCEDURE ActualizarCategoria
	@ID INT,
	@CODIGO VARCHAR(8),
	@NOMBRE VARCHAR(100),
	@OBSERVACION TEXT
AS
UPDATE Categoria SET CodigoCategoria = @CODIGO,
	Nombre = @NOMBRE, Observacion = @OBSERVACION
WHERE IdCategoria = @ID
GO

CREATE PROCEDURE EliminarCategoria
	@ID INT
AS
DELETE FROM Categoria
WHERE IdCategoria = @ID
GO

1) Crear una solución en blanco

@.- File => New =>Project

@.- Other Project Types => Visual Studio Solutions => Blank Solution

@.- Nombre de la solución Tienda.

1) Agregar a la solución las carpetas Modelo y Aplicaciones.

@.- Clic derecho sobre la solución => Add =>New Solution Folder

@.- Asignar el nombre Modelo

@.- Clic derecho sobre la solución => Add =>New Solution Folder

@.- Asignar el nombre Aplicaciones

1) Crear la capa de entidad.

@.- Sobre la Carpeta Modelo, clic derecho => Add => New Project

@.- Seleccione Windows => Class Library como tipo de proyecto.

@.- Asigne el nombre Tienda.Entidades

@.- Elimine la clase que se crea por defecto (Class1.cs)

@.- Agregue un nuevo Item al proyecto, clic derecho => Add => New Item

@.- Seleccione e tipo Class y asigne el nombre Categoria

@.- Para que la clase sea visible para los demás proyectos le agregamos el modificador public

    public class Categoria;

@.- Creamos los campos y métodos de la clase.

        int _id;
        string _codigo;
        string _nombre;
        string _observacion;

        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public string Codigo
        {
            get { return _codigo; }
            set { _codigo = value; }
        }

        public string Nombre
        {
            get { return _nombre; }
            set { _nombre = value; }
        }

        public string Observacion
        {
            get { return _observacion; }
            set { _observacion = value; }
        }

@.- Creamos los constructores de la clase.

        public Categoria(int Id, string Codigo,
            string Nombre, string Observacion)
        {
            this._id = Id;
            this._codigo = Codigo;
            this._nombre = Nombre;
            this._observacion = Observacion;
        }

        public Categoria(int Id, string Codigo,
           string Nombre)
            : this(Id, Codigo, Nombre, "")
        {
        }

        public Categoria(int Id, string Nombre)
            : this(Id, "", Nombre, "")
        {
        }

        public Categoria()
            : this(0,"", "", "")
        {
        }

2) Crear la capa de Datos.

@.- Sobre la Carpeta Modelo, clic derecho => Add => New Project

@.- Seleccione Windows => Class Library como tipo de proyecto.

@.- Asigne el nombre Tienda.Datos

@.- Elimine la clase que se crea por defecto (Class1.cs)

@.- Agregue un nuevo Item al proyecto, clic derecho => Add => New Item

@.- Seleccione el tipo Class y asigne el nombre DAOCategoria

@.- Para que la clase sea visible para los demás proyectos le agregamos el modificador public

    public class DAOCategoria;

@.- Agregue la referencia al proyecto:

Proyecto Tienda.Datos, clic derecho => Add Referece, Seleccione la ficha Projects, luego ubique el proyecto Tienda.Entidades => Ok

@.- Importamos la referencia para esto agregamos la siguiente instrucción.

using Tienda.Entidades;

@.- Vamos a crear una propiedad que tome la cadena de conexión a la base de datos, esta cadena de conexión será definida en el archivo de configuración de la aplicación sea web (webconfig) o Windows (AppConfig), para tomar esta configuración hacemos referencia a System.Configuration:

Proyecto Tienda.Datos, clic derecho => Add Referece, Seleccione la ficha .NET, luego ubique System.Configuration.

@.- Importamos la referencia para esto agregamos la siguiente instrucción.

using System.Configuration;

@.- Creamos una propiedad llamada CadenaConexion, para este caso preguntamos si es que el campo _cadenaConexion recuperó el valor de un key llamado Conex que estará definido en el archivo de configuración.

        string _cadenaConexion;

        public string CadenaConexion
        {
            get
            {
                if (_cadenaConexion == null)
                {
                    _cadenaConexion = ConfigurationManager.
                        ConnectionStrings["Conex"].ConnectionString;
                }
                return _cadenaConexion;
            }
            set { _cadenaConexion = value; }
        }

@.- Ahora creamos los métodos de acceso a datos, tales como Listar, Insertar, Eliminar, Actualizar.

        public List<Categoria> Listar()
        {
            List<Categoria> lista = new List<Categoria>();

            using (SqlConnection con = new SqlConnection(CadenaConexion))
            {
                con.Open();
                SqlCommand cmd = new SqlCommand("ListarCategorias", con);
                cmd.CommandType = CommandType.StoredProcedure;
                SqlDataReader dr = cmd.ExecuteReader();
                if (dr != null && dr.HasRows)
                {
                    while (dr.Read())
                    {
                        Categoria c = new Categoria((int)dr["Id"],
                            (string)dr["Codigo"], (string)dr["Nombre"],
                            (string)dr["Observacion"]);
                        lista.Add(c);
                    }
                }
            }
            return lista;
        }

        public Categoria TraerPorId(int Id)
        {
            Categoria Categoria = new Categoria();
            using (SqlConnection con = new SqlConnection(CadenaConexion))
            {
                con.Open();
                SqlCommand cmd = new SqlCommand("TraerCategoriaPorId", con);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@ID", Id);
                SqlDataReader dr = cmd.ExecuteReader();
                if (dr != null && dr.HasRows)
                {
                    dr.Read();
                    Categoria = new Categoria((int)dr["Id"],
                        (string)dr["Codigo"], (string)dr["Nombre"],
                        (string)dr["Observacion"]);
                }
            }
            return Categoria;
        }

        public int Insertar(Categoria Categoria)
        {
            int n = -1;
            using (SqlConnection con = new SqlConnection(CadenaConexion))
            {
                con.Open();
                SqlCommand cmd = new SqlCommand("InsertarCategoria", con);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@Codigo", Categoria.Codigo);
                cmd.Parameters.AddWithValue("@Nombre", Categoria.Nombre);
                cmd.Parameters.AddWithValue("@Observacion", Categoria.Observacion);
                n = cmd.ExecuteNonQuery();
            }
            return n;
        }

        public int Actualizar(Categoria Categoria)
        {
            int n = -1;
            using (SqlConnection con = new SqlConnection(CadenaConexion))
            {
                con.Open();
                SqlCommand cmd = new SqlCommand("ActualizarCategoria", con);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@Id", Categoria.Id);
                cmd.Parameters.AddWithValue("@Codigo", Categoria.Codigo);
                cmd.Parameters.AddWithValue("@Nombre", Categoria.Nombre);
                cmd.Parameters.AddWithValue("@Observacion", Categoria.Observacion);
                n = cmd.ExecuteNonQuery();
            }
            return n;
        }

        public int Eliminar(int Id)
        {
            int n = -1;
            using (SqlConnection con = new SqlConnection(CadenaConexion))
            {
                con.Open();
                SqlCommand cmd = new SqlCommand("EliminarCategoria", con);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@Id", Id);
                n = cmd.ExecuteNonQuery();
            }
            return n;
        }

3) Crear la capa de Negocio.

@.- Sobre la Carpeta Modelo, clic derecho => Add => New Project

@.- Seleccione Windows => Class Library como tipo de proyecto.

@.- Asigne el nombre Tienda.Negocio

@.- Elimine la clase que se crea por defecto (Class1.cs)

@.- Agregue un nuevo Item al proyecto, clic derecho => Add => New Item

@.- Seleccione el tipo Class y asigne el nombre BLCategoria

@.- Para que la clase sea visible para los demás proyectos le agregamos el modificador public

    public class BLCategoria

@) Agregue la referencia al proyecto:

Tienda.Datos, clic derecho => Add Referece, Seleccione la ficha Projects, luego seleccione el proyecto Tienda.Entidades y Tienda.Datos => Ok

@.- Importamos la referencia para esto agregamos la siguiente instrucción.

using Tienda.Entidades;
using Tienda.Datos;

@.- Creamos ahora nuestra lógica de negocio, para esto creamos los métodos tales como Listar, TraerPorId, Insertar, Eliminar, Actualizar.

        public List<Categoria> Listar()
        {
            DAOCategoria daCategoria = new DAOCategoria();
            return daCategoria.Listar();
        }

        public Categoria TraerPorId(int Id)
        {
            DAOCategoria daCategoria = new DAOCategoria();
            return daCategoria.TraerPorId(Id);
        }

        public int Insertar(Categoria Categoria)
        {
            DAOCategoria daCategoria = new DAOCategoria();
            return daCategoria.Insertar(Categoria);
        }

        public int Actualizar(Categoria Categoria)
        {
            DAOCategoria daCategoria = new DAOCategoria();
            return daCategoria.Actualizar(Categoria);
        }

        public int Eliminar(int Id)
        {
            DAOCategoria daCategoria = new DAOCategoria();
            return daCategoria.Eliminar(Id);
        }

3) Crear la Aplicación.

@.- Sobre la Carpeta Aplicaciones, clic derecho => Add => New Project

@.- Seleccione Windows => Windows Forms Application como tipo de proyecto.

@.- Asigne el nombre TiendaWindows


@.- Diseñe el siguiente formulario

GroupBox

gbDatos; gbControl => (gbDatos Contiene a todos los TextBox, gbControl contiene a los Button)

TextBox

txtCodigo; txtNombre; txtObservacion =>(txtObservacion debería mostrarse multilinea)

Button

btnNuevo, btnGrabar, btnEditar, btnEliminar, btnSalir

DataGridView

dgvDatos

@.- Personalize el control dgvDatos, agregue las columnas Id, Código, Nombre, Observación. Modifique la propiedad Visible=False de la columna Id.

@.- El diseño del formulario debería mostrar el siguiente aspecto.

@) Agregue la referencia al proyecto:

Proyecto TiendaWindows, clic derecho => Add Referece, Seleccione la ficha Projects, luego seleccione el proyecto Tienda.Entidades y Tienda.Negocio => Ok

@.- Agregue un nuevo Item al proyecto, clic derecho => Add => New Item

@.- Seleccione e tipo Application Configuration File, el nombre será por defecto App.config.

@.- Abrimos el archivo App.config y agregamos la siguiente instrucción después de <configuration>.

  <connectionStrings>
    <add name="Conex" connectionString="Data Source=ServidorBD;Initial Catalog=Tienda; 
         UID = UsuarioBD;PWD = PasswordBD"/>
  </connectionStrings>

@.- Importamos la referencia para esto agregamos la siguiente instrucción.

using Tienda.Entidades;
using Tienda.Negocio;

@.- Declaramos las variables generales

       List<Categoria> lista = null;
        BLCategoria blCategoria = new BLCategoria();
        Categoria c;
        bool _nuevo = false;

@.- Creamos un método que permita activar los controles

        private void ActivarControlDatos(Control Contenedor, bool Estado)
        {
            foreach (var item in Contenedor.Controls)
            {
                if (item.GetType() == typeof(TextBox))
                {
                    ((TextBox)item).Enabled = Estado;
                }
            }
        }

@.- Creamos un método que limpie los controles

        private void LimpiarControl(Control Contenedor)
        {
            foreach (var item in Contenedor.Controls)
            {
                if (item.GetType() == typeof(TextBox))
                {
                    ((TextBox)item).Clear();
                }
            }
        }

@.- Creamos un método que Active los Botones

        private void ActivarButton(bool Estado)
        {
            btnNuevo.Enabled = Estado;
            btnGrabar.Enabled = !Estado;
            btnEliminar.Enabled = Estado;
            btnSalir.Enabled = Estado;
        }

@.- Creamos el método CargarDatos

        private void CargarDatos()
        {
            if (lista.Count > 0)
            {
                dgvDatos.Rows.Clear();
                for (int i = 0; i < lista.Count; i++)
                {
                    dgvDatos.Rows.Add(lista[i].Id, lista[i].Codigo,
                        lista[i].Nombre, lista[i].Observacion);
                }
            }
        }

@.- Botón Nuevo

        private void btnNuevo_Click(object sender, EventArgs e)
        {
            _nuevo = true;
            ActivarControlDatos(gbDatos, true);
            btnEditar.Text = "Cancelar";
            ActivarButton(false);
            LimpiarControl(gbDatos);
            txtCodigo.Focus();
        }

@.- Botón Grabar

        private void btnGrabar_Click(object sender, EventArgs e)
        {
            int n = -1;
            if (_nuevo)
            {
                c = new Categoria(0, txtCodigo.Text,
                    txtNombre.Text, txtObservacion.Text);
                n = blCategoria.Insertar(c);
            }
            else
            {
                c.Codigo = txtCodigo.Text;
                c.Nombre = txtNombre.Text;
                c.Observacion = txtObservacion.Text;
                n = blCategoria.Actualizar(c);
            }
            if (n > 0)
            {
                MessageBox.Show("Datos grabados correctamente", "Aviso", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                ActivarControlDatos(gbDatos, false);
                ActivarButton(true);
                dgvDatos.Enabled = true;
                LimpiarControl(gbDatos);
                btnEditar.Text = "Editar";
                lista = blCategoria.Listar();
                CargarDatos();
            }
            else { MessageBox.Show("Error al grabar", "Aviso", 
                MessageBoxButtons.OK, MessageBoxIcon.Error); }
        }

@.- Botón Editar

        private void btnEditar_Click(object sender, EventArgs e)
        {
            if (btnEditar.Text == "Cancelar")
            {
                _nuevo = false;
                LimpiarControl(gbDatos);
                ActivarControlDatos(gbDatos, false);
                ActivarButton(true);
                dgvDatos.Enabled = true;
                btnEditar.Text = "Editar";
            }
            else
            {
                if (dgvDatos.RowCount > 0)
                {
                    c = blCategoria.TraerPorId((int)dgvDatos[0, dgvDatos.
                        CurrentRow.Index].Value);
                    txtCodigo.Text = c.Codigo;
                    txtNombre.Text = c.Nombre;
                    txtObservacion.Text = c.Observacion;
                    ActivarControlDatos(gbDatos, true);
                    ActivarButton(false);
                    dgvDatos.Enabled = false;
                    btnEditar.Text = "Cancelar";
                }
            }
        }

@.- Botón Eliminar

        private void btnEliminar_Click(object sender, EventArgs e)
        {
            if (dgvDatos.RowCount > 0)
            {
                c = blCategoria.TraerPorId((int)dgvDatos[0, dgvDatos.
                    CurrentRow.Index].Value);
                DialogResult rpta = 
                    MessageBox.Show("Desea eliminar el registro", "Eliminar",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (rpta == System.Windows.Forms.DialogResult.Yes)
                {
                    int n = blCategoria.Eliminar(c.Id);
                    if (n > 0)
                    {
                        MessageBox.Show("Registro eliminado", "Aviso", 
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                        lista = blCategoria.Listar();
                        CargarDatos();
                    }
                    else { MessageBox.Show("Error al eliminar", "Aviso", 
                        MessageBoxButtons.OK, MessageBoxIcon.Error); }
                }

            }
        }

@.- Botón Salir

}

        private void btnSalir_Click(object sender, EventArgs e)
        {
            Close();
        }

@.- Ejecutar la Aplicación

13 comentarios en “Desarrollo de Aplicaciones N-Capas

  1. buenas Eduardo, muy buen post, tengo un par de consultas: 1. con referencia al diagrama de clases en la tabla Pedido tiene una relacion de uno a muchos con Detalle Pedido, entonces cuando creo la clase pedido ademas de las propiedades que crean en la clase, se crea una propiedad que contenga la colleccion por ejemplo ICOLLECTION Lista_detallePedido;
    2. Por ejempo en la tabla misma tabla Pedido tiene dos llaves foraneas idCliente y idUsuario esas dos columnas en la clase Producto, se representan como propiedades normales o como propiedades que se expresan o representan como llaves foraneas, espero me haberme explicado y muchas gracias por la atencion.

    • Saludos Cristian, vamos a responder tu pregunta con este ejemplo:
      La clase pedido tendria las siguientes propiedades:

      public class Pedido
      {
              public int IdPedido { get; set; }
              public DateTime Fecha { get; set; }
              public string Observacion { get; set; }
              public Usuario Usuario { get; set; }
              public Cliente Cliente{ get; set; }
              public bool Estado { get; set; }
              public List<Detalle> Detalle { get; set; }
      }
      

      Para el caso de los detalles en la clase Pedido estoy creando una propiedad llamada Detalle, el cual me dovelvera una coleccion de la clase Detalle (List).
      Para la relación IdCliente e IdUsuario estoy creando una propiedad de tipo Usuario y Cliente respectivamente.
      Espero haber aclarado tus dudas, ah por cierto mi nombre es Donald.

  2. Hola Donald, jejeje las disculpas de caso, muchas gracias por su respuesta y realmente me quedo muy clara la duda que tenia, muchas gracias…dejame recalcar que el post esta muy bien explicado…saludos…!!!

  3. Buenas noches profesor… no seria mucha molestia el pedirle que termine el caso de los pedidos junto con la técnica atomizar (con transacciones).. le estaría agradecido…

Replica a Eduardo Cancelar la respuesta