Вы находитесь на странице: 1из 19

Programacin en 3 capas

Hola a todos:

Despus de tantos meses de tener abandonado el Blog por fin hoy se libera un espacio en mi agenda, tiempo que he
decidido compartir con todos y cada uno de ustedes.

En este articulo hablare y tratare de explicar con los detalles mas mnimos que es la arquitectura 3 capas, cuales son sus
ventajas, como empezar un proyecto 3 capas, cuales son las diferencias entre cada una de ellas, como comunicarlas y
como crear un proyecto con la arquitectura 3 capas utilizando Visual Studio 2012.

Antes de comenzar a leer este articulo recuerde que: El objetivo no es otro mas que el de orientar a los Parvulos
.Net sobre la arquitectura de software 3 capas, todo lo escrito en este articulo no es ensayado, no es revisado por nadie
mas, por lo cual podra contener errores gramaticales y sintcticos, el articulo y sus conceptos no pretenden ser la
verdad absoluta del tema, sintase en confianza de dejar sus comentarios y opiniones en la seccin de comentarios al
final del mismo y si lo considera prudente enveme un correo electrnico por medio del formulario de contacto y por
ultimo si el articulo le es de utilidad por favor considere dejar un comentario de agradecimiento.

Requisitos: Visual Studio 2012, Framework 4.0, el proveedor de datos SqlCompact 4.0 instalado en su equipo y muchas
ganas de aprender.

Como siempre recomiendo encarecidamente que antes de descargar los proyectos de ejemplo (que les pondr al final de
articulo), traten de hacerlo ustedes mismos siguiendo paso a paso todo lo que se mencionara aqu, si tienen dudas en
uno en especifico no duden en contactarme.

Dicho todo lo anterior, comencemos

Arquitectura 3 capas en .Net

Ha creado usted software?Si?, entonces sabe lo complejo que resulta crear rutinas y funciones para cada uno de
los formularios, importar todas las referencias del motor de base de datos en cada uno de los formularios, cambiar cdigo
aqu y all (porque tiene copias del mismo cdigo en muchos lugares), escribir la lgica de validacin de campos dentro
del evento, corregir los bugs que pudieran presentarse y no se diga de implementarles mejoras al software, etc., No?
entonces no se preocupe este es un buen manual de como evitarse muchos dolores de cabeza en diseo de su
arquitectura a seguir.

Para que se de una mejor idea de que hablo, por favor descargue este proyecto de ejemplo, ejectelo, analice el cdigo,
observe como para realizar una misma funcionalidad en dos lugares diferentes tuvimos que escribir casi las mismas
lneas de cdigo.

A partir de aqu en adelante estaremos trabajando con el proyecto descargado, aplicndole la Arquitectura 3 capas para
demostrar como esta Arquitectura de Diseo nos ayuda a:
Separar responsabilidades, cada capa tiene una funcin especifica y no interviene con la de las dems.
Reutilizar cdigo
La separacin de roles en tres capas, hace mas fcil reemplazar o modificar a una, sin afectar a los mdulos
restantes
El cdigo de la capa intermedia puede ser reutilizado por mltiples
Capacidad de migrar nuestro motor de Base de Datos sin grandes impactos al resto del proyecto.
Poder cambiar el Front de nuestra aplicacin sin afectar a la lgica de nuestra aplicacin ni a la Base de datos
Bien como ya hemos mencionado La Arquitectura de diseo 3 capas, consiste en dividir el diseo del software en sus
tres principales componentes:
1. La Interfaz o UI (User interface): Esta Capa es la encargada de interactuar con el usuario, es decir, son
aquellas ventanas, mensajes, cuadros de dilogos o paginas web (en el caso del desarrollo web), que el usuario final
utiliza para comunicarse con la aplicacin, por medio de esta capa el usuario solicita que se ejecuten las tareas
proporcionando parmetros de entrada y recibiendo datos como respuesta. Esta capa se comunica con la capa de
Lgica de Negocio, enviando y solicitando informacin y con la capa de Entidades usando sus objetos para enviar y
recibir esta informacin.
2. La lgica de negocio o Business Logic: Se encarga de implementar, como su nombre lo dice, la lgica del
negocio, es decir, todo lo que el Software debe de considerar antes de realizar una accin o el proceso que debe de
seguir despus de realizar una accin. Por ejemplo: Antes de solicitar a la capa de Datos la insercin de un grupo de
registros en una tabla, valida que vayan todos los campos mandatorios dentro de esa solicitud si esta condicin no se
cumple entonces rechaza la insercin e informa del usuario del status de su solicitud; otro ejemplo podria ser, solicitar a
la base de datos que valide la presencia de un registro antes de insertar el siguiente, validar los tipos de datos, etc. esos
ejemplos por mencionar los mas bsicos y generales. Esta capa recibe de la Capa de Presentacin las solicitudes, valida
que las condiciones que establece el negocio se cumplan antes de realizar dicha accin o de hacer la respectiva solicitud
a la Capa de Acceso a Datos
3. El acceso a Datos o Data Access: Esta capa es la encargada de la comunicacin con la base de datos, en esta
capa descansaran todas nuestras acciones CRUD (Create, Read, Update y Delete), ser la nica que sabr que motor
de base de datos se esta utilizando pero le ser completamente desconocido el front, es decir, jams sabr si nuestra
aplicacin es una aplicacin web o desktop. Se encarga de recibir las peticiones de la Capa de Lgica de Negocio,
ejecutar dichas acciones y devolver el resultado a la misma capa.
4. Capa de Entidades o Entity Layer: Aunque aparentemente es una cuarta capa realmente no lo es, esta capa se
encarga de contener todos aquellos objetos (clases) que representan al negocio, y esta es la nica que puede ser
instanciada en las 3 capas anteriores, es decir, solo ella puede tener comunicacin con el resto pero su funcin se limita
a nicamente ser un puente de transporte de datos. Esta capa complementa a la Capa de Negocio
Para una mejor compresin de la comunicacin de las 3 capas:

Hasta aqu, hemos visto la teora de lo que representa la Arquitectura 3 Capas, pero

Como es que debo representar la Arquitectura 3 Capas en un proyecto de Visual Studio?

Para haya es a donde vamos.

1. Abra el Visual Studio 2012 y cree un proyecto Vaco y nmbrelo CSharp-3Capas-Primer Entrega
2. Dirjase al Explorador de soluciones y haga click derecho sobre el proyecto que acabamos de crear:

3. Del men desplegado seleccione Agregar->Nuevo Proyecto:

4. Seleccione, Instalado > Visual C# > Windows > Aplicacin de Windows Forms > En el campo Nombre escriba,
Tienda-Presentacion y presione el botn Aceptar.
5. Repita el paso 2, 3 y en el 4, seleccione un tipo de proyecto Biblioteca de Clases y establezca como nombre
Tienda-LogicaNegocio

6.Repita el paso 2, 3 y en el 4, seleccione un tipo de proyecto Biblioteca de Clasesutilice el nombre Tienda-


AccesoDatos

7. Repita el paso 2, 3 y en el 4, seleccione un tipo de proyecto Biblioteca de Clases utilice el nombre Tienda-
Entidades

Como va nuestro diseo'?

Observe que cuando creamos el proyecto principal en automtico se creo un proyecto vaco, eliminemos ese proyecto
para dejar la siguiente estructura:
Ahora ya tenemos nuestra estructura completa, observe que creamos 4 proyectos dentro del principal (que lo iniciamos
como proyecto vaco), recuerde que el proyecto de Entidades en este caso Tienda-Entidades no es una capa, mas bien,
complementa a la capa de Lgica de Negocio.

Continuemos con nuestro diseo

Capa de Entidades

Recuerde que en esta capa estarn alojados los objetos (clases) con los cuales estaremos trabajando, con estos objetos
estaremos persistiendo las tablas de la base de datos que utilizaremos.

La base de datos que usaremos contiene una sola tabla llamada Producto la cual contiene 5 campos (Id int,
Descripcin nvarchar, Marca nvarchar, Precio nvarchar), por lo cual la Capa de Entidades contendr un Objeto
llamado Producto con 5 propiedades publicas cada uno de ellos respetando el tipo de dato con el cual esta declarado en
la base de datos.

Para declarar nuestra Entidad Producto:

1. Agregue una clase al proyecto Tienda-Entidades y llmela EProducto (La letra E es por convecin, es decir, todos
los objetos de nuestra capa de Entidades llevaran la letra E al principio para que desde donde las lleguemos a utilizar
sepamos que ese Objeto es una Entidad evitando con esto confusiones con otros objetos), dentro agregue las siguientes
lneas de cdigo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tienda_Entidades
{
public class EProducto
{
public int Id { get; set; }
public string Descripcion { get; set; }
public string Marca { get; set; }
public decimal Precio { get; set; }
}
}

Si tuviramos mas tablas en nuestra base de datos tendramos que crear la misma cantidad de objetos en nuestra capa
de Entidades y dentro contendran la misma cantidad de propiedades como campos tiene la tabla siempre respetando el
tipo de dato con lo que estos campos estn declarados.
Capa de acceso a Datos
Recordemos que la capa de datos es usada por la capa de lgica y la capa de lgica es llamada por la capa de
presentacin, as que usaremos ese mismo orden para crear nuestras configuraciones y nuestras lneas de cdigo.

1. Agreguemos un archivo de configuracin (App.Config) a nuestra capa de datos recuerde que una de las caractersticas
principales del archivo de configuraciones es que podemos establecer una cadena de conexin la cual accederemos
fcilmente desde cualquier lugar del proyecto que lo contiene, que es lo que en esta ocasin nos interesa.

Nuestro archivo de configuraciones lo tenemos que agregar en nuestro proyecto de presentacin, y no porque lo vaya a
utilizar sino que nuestro software cada vez que arranque buscara este archivo en el directorio desde donde se este
ejecutando la aplicacin, para efectos de prueba ser en la carpeta ..bin\debug pero cuando nuestro proyecto este
instalado, el archivo quedara desplegado justo en la carpeta raz de nuestra instalacin junto con el .exe por tal motivo
deber de estar en el mismo proyecto que esta marcado como proyecto de inicio.

Para agregar un archivo de configuraciones siga estos pasos:

- Click derecho sobre el proyecto Tienda-AccesoDatos > Agregar > Nuevo elemento

2. En el proyecto que descargaron anteriormente si observaron viene embebida un archivo de base de datos
llamado DataBase1.sdf que noes otra cosa mas que un archivo de base de datos propios del motor SQlCompact, cree
una carpeta en la unidad C y llmela Proyecto-3Capas, despus copien este archivo en ese path.

3. Abran el archivo de configuraciones desde el Explorador de soluciones, Copien las siguientes lneas de cdigo, borren
el contenido del App.Config y pguenlas en su lugar:

<?xml version="1.0" encoding="utf-8" ?>


<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="cnnString"
connectionString="Data Source=C:\Proyecto-3Capas\Database1.sdf"
providerName="Microsoft.SqlServerCe.4.0" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

Observen que el DataSource apunta a la carpeta que acabamos de crear en la unidad C Data Source=C:\Proyecto-
3Capas\Database1.sdf", esta cadena en proyetos reales normalmente apuntara a un servidor de datos, pero para fines
ilustrativos, este directorio nos servir muy bien.
Volvamos a nuestra Capa de Datos

4. Agreguemos las referencias a las libreras System.Configuration para esto, Click sobre nuestra capa de datos
(proyecto Tienda-AccesoDatos) > Agregar Referencia

5. Agregue una segunda referencia ahora a System.Data.SqlServeCe (esta librera no siempre aparece, si este es su
caso presione el botn Examinar localice la Dll dentro de archivos de programa y seleccinela), presione Aceptar.

6. Ya tenemos nuestro App.Config(en el proyecto de arranque) apuntando a nuestra base de datos y tenemos las dos
referencias que necesitamos, System.Configuration para poder accesar y leer el archivo de configuraciones y
el System.Data.SqlServerCe para poder usar los objetos de acceso a datos propios del motor SQLCOMPACT en nuestra
Capa de Datos.

Como nuestra capa de Acceso a Datos, debe de tener la capacidad de Insertar, Leer, Actualizar y Eliminar registros de la
tabla Productos, requiere de una comunicacin directa con la capa de Entidades, para por ejemplo, al momento de que
se le solicite la insercin de un Producto en lugar de enviarle 5 parmetros con los datos del producto se le envi un
Objeto y Cual ser este objeto? nada mas y nada menos que nuestro objeto EProducto creado en la capa de
Entidades, de esta manera ya no trabajaremos con datos sino con objetos llenando, enviando y leyendo propiedades.

Para lograr la comunicacin entre la Capa de Datos y la Capa de Entidades se requiere de la referencia de una en la
otra, en este caso la referencia de la Capa de Entidades dentro de la Capa de Datos, para ello:

7. Click derecho sobre nuestro proyecto Tienda-AccesoDatos > Agregar Referencia


8. Solucin > Proyectos > Seleccione Tienda-Entidades

Observe como se a creado un nuevo elemento en nuestra carpeta de Referencias del proyecto Tienda-AccesoDatos

9. Inserte una clase nueva llamada ProductoDal de donde Dal vendr de Data Access Layer, dentro de la clase que
acaba de crear tiene que declarar el espacio de nombres System.Configuration, System.Data.SqlServerCe y del proyecto
de Entidades, adems tiene que declarar la clase como publica (para que la Capa de Lgica de Negocio pueda tener
acceso a ella)
Ya tenemos el puente de comunicacin entre nuestras Entidades y nuestra Capa de Datos. Solo resta comenzar a
codificar las acciones que querramos hacer con nuestra tabla Producto, recuerde que el objeto ProductoDal nicamente
tiene como responsabilidad trabajar con todo aquello relacionado con Producto, as que comencemos haciendo la
codificacin para Insertar, Traer todos los registros existentes en nuestra tabla Producto, Traer, Actualizar y Eliminar por
Id.

Para hacer esta tarea mas sencilla le proporcionare el cdigo que deber de poner en la clase ProductoDal, pero, trate
de escribir el cdigo para vaya analizando la estructura del mismo.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//nuestras importaciones del Espacio de nombres que estaremos utilizando,
//recuerde que estas son las referencias que realizamos hace unos momentos...
using System.Configuration;
using System.Data.SqlServerCe;
using Tienda_Entidades;
namespace Tienda_AccesoDatos
{
//Definimos el acceso de nuestra clase como public, asegurando con esto su
accesibilidad desde
//otros proyectos.
public class ProductoDal
{
//Primero y siguiendo el orden de las acciones CRUD
//Crearemos un Mtodo que se encarga de insertar un nuevo Producto es nuestra
tabla Producto
/// <summary>
/// Inserta un nuevo Producto en la tabla Producto
/// </summary>
/// <param name="producto">Entidad contenedora de los valores a insertar</param>
/// <autor>Jos Luis Garca Bautista</autor>
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 Accin 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();
}
}
}

/// <summary>
/// Devuelve una lista de Productos ordenados por el campo Id de manera Ascendente
/// </summary>
/// <returns>Lista de productos</returns>
/// <autor>Jos Luis Garca Bautista</autor>
public List<EProducto> GetAll()
{
//Declaramos una lista del objeto EProducto la cual ser la encargada de
//regresar una coleccin de los elementos que se obtengan de la BD
//
//La lista substituye a DataTable utilizado en el proyecto de ejemplo
List<EProducto> productos = new List<EProducto>();

using (SqlCeConnection cnx = new


SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString()))
{
cnx.Open();

const string sqlQuery = "SELECT * FROM Producto ORDER BY Id ASC";


using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery, cnx))
{
SqlCeDataReader dataReader = cmd.ExecuteReader();
//
//Preguntamos si el DataReader fue devuelto con datos
while (dataReader.Read())
{
//
//Instanciamos al objeto Eproducto para llenar sus propiedades
EProducto producto = new EProducto
{
Id =
Convert.ToInt32(dataReader["Id"]),
Descripcion =
Convert.ToString(dataReader["Descripcion"]),
Marca =
Convert.ToString(dataReader["Marca"]),
Precio =
Convert.ToDecimal(dataReader["Precio"])
};
//
//Insertamos el objeto Producto dentro de la lista Productos
productos.Add(producto);
}
}
}
return productos;
}

/// <summary>
/// Devuelve un Objeto Producto
/// </summary>
/// <param name="idProducto">Id del producto a buscar</param>
/// <returns>Un registro con los valores del Producto</returns>
/// <autor>Jos Luis Garca Bautista</autor>
public EProducto GetByid(int idProducto)
{
using (SqlCeConnection cnx = new
SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString()))
{
cnx.Open();

const string sqlGetById = "SELECT * FROM Producto WHERE Id = @id";


using (SqlCeCommand cmd = new SqlCeCommand(sqlGetById, cnx))
{
//
//Utilizamos el valor del parmetro idProducto para enviarlo al
parmetro declarado en la consulta
//de seleccin SQL
cmd.Parameters.AddWithValue("@id", idProducto);
SqlCeDataReader dataReader = cmd.ExecuteReader();
if (dataReader.Read())
{
EProducto producto = new EProducto
{
Id = Convert.ToInt32(dataReader["Id"]),
Descripcion = Convert.ToString(dataReader["Descripcion"]),
Marca = Convert.ToString(dataReader["Marca"]),
Precio = Convert.ToDecimal(dataReader["Precio"])
};

return producto;
}
}
}

return null;
}

/// <summary>
/// Actualiza el Producto correspondiente al Id proporcionado
/// </summary>
/// <param name="producto">Valores utilizados para hacer el Update al
registro</param>
/// <autor>Jos Luis Garca Bautista</autor>
public void Update(EProducto producto)
{
using (SqlCeConnection cnx = new
SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString()))
{
cnx.Open();
const string sqlQuery =
"UPDATE Producto SET Descripcion = @descripcion, Marca = @marca,
Precio = @precio WHERE Id = @id";
using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery, cnx))
{
cmd.Parameters.AddWithValue("@descripcion", producto.Descripcion);
cmd.Parameters.AddWithValue("@marca", producto.Marca);
cmd.Parameters.AddWithValue("@precio", producto.Precio);
cmd.Parameters.AddWithValue("@id", producto.Id);

cmd.ExecuteNonQuery();
}
}
}
/// <summary>
/// Elimina un registro coincidente con el Id Proporcionado
/// </summary>
/// <param name="idproducto">Id del registro a Eliminar</param>
/// <autor>Jos Luis Garca Bautista</autor>
public void Delete(int idproducto)
{
using (SqlCeConnection cnx = new
SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString()))
{
cnx.Open();
const string sqlQuery = "DELETE FROM Producto WHERE Id = @id";
using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery, cnx))
{
cmd.Parameters.AddWithValue("@id", idproducto);

cmd.ExecuteNonQuery();
}
}
}
}
}

Observe como desde nuestros diferentes Mtodos y funciones estamos haciendo uso del objeto EProducto declarado en
la capa de EntidadesObserve tambin como nuestra clase ProductosDal no valida que el valor de las propiedades
de EProducto contengan datos o sean del tipo de dato correcto porque ese es trabajo de?La Capa de Lgica de
Negocio

Capa de Lgica de Negocio


Recuerde que la capa de Lgica es la encargada de establecer toda la lgica que el negocio establece para llevar a cabo
una accin o despus de haber realizado un proceso, y esta se comunica directamente con la Capa de Acceso a Datos,
por lo cual tenemos que hacer la referencia al Proyecto Tienda-AccesoDatos y para ello:

1. Click derecho sobre nuestro proyecto Tienda-LogicaNegocio > Agregar Referencia

8. Solucin > Proyectos > Seleccione Tienda-AccesoDatos y Tienda-Entidades


Observe como se acaban de agregar nuestras referencias:

9. Agregue una nueva clase y llmela ProductoBol, haga los using de las referencias que acabamos de crear,
establezca el nivel de acceso como public y copie la siguiente estructura de cdigo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//
//Hacemos las importaciones del espacio de nombres de los dos proyectos que referenciamos
//observe como esta capa solo referencio a Tienda-AccessData y no a Tienda-Presentacion
//observe tambin como aqu no es requerida la referencia a System.Data.SqlServerCe
using Tienda_AccesoDatos;
using Tienda_Entidades;
namespace Tienda_LogicaNegocio
{
public class ProductoBol
{
//Instanciamos nuestra clase ProductoDal para poder utilizar sus miembros
private ProductoDal _productoDal = new ProductoDal();
//
//El uso de la clase StringBuilder nos ayudara a devolver los mensajes de las
validaciones
public readonly StringBuilder stringBuilder = new StringBuilder();

//
//Creamos nuestro mtodo para Insertar un nuevo Producto, observe como este mtodo
tampoco valida los el contenido
//de las propiedades, sino que manda a llamar a una Funcin que tiene como tarea
nica hacer esta validacin
//
public void Registrar(EProducto producto)
{
if(ValidarProducto(producto))
{
if (_productoDal.GetByid(producto.Id) == null)
{
_productoDal.Insert(producto);
}
else
_productoDal.Update(producto);

}
}

public List<EProducto> Todos()


{
return _productoDal.GetAll();
}

public EProducto TraerPorId(int idProduct)


{
stringBuilder.Clear();

if (idProduct == 0) stringBuilder.Append("Por favor proporcione un valor de Id


valido");

if(stringBuilder.Length == 0)
{
return _productoDal.GetByid(idProduct);
}
return null;
}

public void Eliminar(int idProduct)


{
stringBuilder.Clear();

if (idProduct == 0) stringBuilder.Append("Por favor proporcione un valor de Id


valido");

if (stringBuilder.Length == 0)
{
_productoDal.Delete(idProduct);
}
}

private bool ValidarProducto(EProducto producto)


{
stringBuilder.Clear();

if (string.IsNullOrEmpty(producto.Descripcion)) stringBuilder.Append("El campo


Descripcin es obligatorio");
if (string.IsNullOrEmpty(producto.Marca))
stringBuilder.Append(Environment.NewLine + "El campo Marca es obligatorio");
if (producto.Precio <= 0) stringBuilder.Append(Environment.NewLine + "El campo
Precio es obligatorio");

return stringBuilder.Length == 0;
}
}
}

Analice cada uno de los mtodos y funciones que creamos en nuestro primer objeto de nuestra capa de Negocio,
observe:
Cada uno de ellos tiene una sola responsabilidad
La capa de negocio cumple otras tareas y no solo la de ser un puente entre nuestra Capa de Datos y nuestra
Capa de Presentacin
Como es que estamos usando nicamente objetos y no controles, recuerde que esta capa tampoco sabe que
tipo de proyecto es el que la estar usando.
Observe que esta capa no tiene referencias a System.Configuration ni mucho menos
a System.Data.SqlServerCe.
Observe que en esta capa tambin se utiliza la Capa de Entidades.
Capa de Presentacin o User Interface
Le toca el turno a la Capa de Presentacin entrar en escena, esta capa ser la encargada de interactuar con el usuario,
la vista de todo nuestro sistema, la encargada de recoger las peticiones del usuario y de pasar esta misma a la capa de
Lgica de Negocio, todo lo que el usuario requiera se la solicitara a esta y todo lo que Lgica de Negocio devuelva esta
se la mostrar al usuario en forma de datos.

Para configurar nuestra Capa de Presentacin.

10. Haga las referencias a los proyecto Tienda-LogicaNegocio y Tienda-Entidades


11. En el formulario que tenemos por default llamado Form1 disee una interfaz como la siguiente:

12. Observe las siguientes lneas de cdigo, genere los eventos involucrados y copie el cdigo de ejemplo:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
//
//Hacemos las importaciones del espacio de nombres de los dos proyectos que referenciamos
//observe como esta capa solo referencio a Tienda-LogicNegocio y a Tienda-Entidades
//observe como no se referencia a la clase de acceso a Datos
using Tienda_LogicaNegocio;
using Tienda_Entidades;
namespace Tienda_Presentacion
{
public partial class Form1 : Form
{
//
//
//Creamos las instancias de la clase Eproducto y ProductoBol
private EProducto _producto;
private readonly ProductoBol _productoBol = new ProductoBol();

public Form1()
{
InitializeComponent();
}

//
//Creamos los mtodos generales llenando y leyendo objetos
//
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");
}
}

private void TraerTodos()


{
List<EProducto> productos = _productoBol.Todos();

if (productos.Count > 0)
{
dgvDatos.AutoGenerateColumns = false;
dgvDatos.DataSource = productos;
dgvDatos.Columns["columnId"].DataPropertyName = "Id";
dgvDatos.Columns["columnDescripcion"].DataPropertyName = "Descripcion";
dgvDatos.Columns["columnMarca"].DataPropertyName = "Marca";
dgvDatos.Columns["columnPrecio"].DataPropertyName = "Precio";
}
else
MessageBox.Show("No existen producto Registrado");
}

private void TraerPorId(int id)


{
try
{
_producto = _productoBol.TraerPorId(id);

if (_producto != null)
{
txtId.Text = Convert.ToString(_producto.Id);
txtDescripcion.Text = _producto.Descripcion;
txtMarca.Text = _producto.Marca;
txtPrecio.Text = Convert.ToString(_producto.Precio);
}
else
MessageBox.Show("El Producto solicitado no existe");
}
catch (Exception ex)
{
MessageBox.Show(string.Format("Error: {0}", ex.Message), "Error
inesperado");
}
}

private void Eliminar(int id)


{
try
{
_productoBol.Eliminar(id);

MessageBox.Show("Producto eliminado satisfactoriamente");

TraerTodos();
}
catch (Exception ex)
{
MessageBox.Show(string.Format("Error: {0}", ex.Message), "Error
inesperado");
}
}

//
//
//Usamos nuestros metodos y funciones generales, observe como no hemos repetido
codigo en ningun lado
//haciendo con esto que nuestras tareas de actualizacion sean mas sencillas para
nosotros o para
//al asignado en realizarlas...
private void btnAgregar_Click(object sender, EventArgs e)
{
Guardar();
}

private void txtId_KeyDown(object sender, KeyEventArgs e)


{
if (e.KeyData == Keys.Enter && !string.IsNullOrWhiteSpace(txtId.Text))
{
e.SuppressKeyPress = true;

TraerPorId(Convert.ToInt32(txtId.Text));
}
}

private void txtPrecio_KeyDown(object sender, KeyEventArgs e)


{
if (e.KeyData == Keys.Enter)
{
e.SuppressKeyPress = true;

Guardar();
}
}

private void btbnBuscar_Click(object sender, EventArgs e)


{
if (!string.IsNullOrWhiteSpace(txtId.Text))
{
TraerPorId(Convert.ToInt32(txtId.Text));
}
}

private void btnEliminar_Click(object sender, EventArgs e)


{
if (!string.IsNullOrWhiteSpace(txtId.Text))
{
Eliminar(Convert.ToInt32(txtId.Text));
}
}
}
}

De nuevo observe como esta capa desconoce si existe una capa de Datos y mucho menos que motor de base de datos
se utiliza, tampoco se encarga de implementar las reglas de validacin ni de lgica de negocio, su tarea es interactuar
con el usuario pidiendo y desplegando informacin.

Que es lo que falta?

Solo nos resta probar el proyectopero eso, ser tarea suyaEjecute el proyecto, inserte un nuevo registro, busque un
registro por id, edite su informacin, elimine un producto, depure el cdigo lnea a lnea para viva de paso a paso como
es que va pasando de capa de capa enviando y trayendo informacin.

Aqu termina nuestro articulo sobre Arquitectura 3 Capas, espero haya sido de su agrado y que la explicacin haya sido
lo bastante clara, en caso de que tenga alguna duda por favor deje su pregunta en la seccin de comentarios o
escrbame por medio del formulario de contacto.

Escribir este articulo me llevo mas de 4 horas, dejar un comentario de agradecimiento le tomara 5 minutos.

Saludos desde Monterrey, Nuevo Len Mxico!

Вам также может понравиться