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
bacan profe…. a revisarlo completo
Revisarlo e implementarlo Eduardo, a poner en practica lo que se explica en este post.
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:
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.
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…!!!
Cristian gracias por tus buenos comentarios, cualquier duda aqui estamos.
Saludos
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…
El caso práctico de todas maneras lo vamos a realizar, pero será utilizando un servicio web.
Muy bueno, se agradece el aporte. ¿No tendrás uno similar en Visual Basic?
Gracias por el comentario. Es un poco complicado que lo haga en VB.
Entiendo, veré si me sale y te lo paso en Word para que lo cuelgues en tu blog.
Gracias
Buen post profe
Solo me queda una duda y es que hacia el «int n=-1;» ¿por qué menos uno?
Gracias Profe!!