Sin mas preámbulos, empecemos a definir la estructura del proyecto.
Me gusta trabajar de la siguiente manera:
1. Entity: Entidades que representan las tablas de base de datos.
2. Data: Hace referencia a la capa Entity. En esta capa suelo usar una clase Connection y una interfaz IRepository, este viene a ser Repository Pattern. Aquí hace uso de nuestro querido amigo ADO.NET
3. Business: Hace referencia a la capa Entity y Data. Encapsula la logica de la Data y la retorna. Es nuestra tradicional capa de negocio. Es la que se comunicara directamente con nuestro proyecto web.
4. Web. Proyecto MVC5, hace referencia a la capa Entity y Business.
Para esta entrada, nos concentraremos en las dos primeras capas, vale decir, en la
ENTITY y en la
DATA.
Empecemos a crear una solución haciendo uso del Visual Studio 2017 (para mi caso) llamada Ventas. Vamos agregando proyectos a nuestra solución del tipo Class Library o Biblioteca de Clases por cada capa.
Primera Capa: Entity
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Entity
{
public class Producto
{
[Display(Name = "Código")]
public int Id { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido.")]
[Display(Name = "Nombre")]
public string Nombre { get; set; }
[Display(Name = "Descripción")]
public String Descripcion { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido.")]
[Display(Name ="Precio Unitario")]
public double PrecioUnitario { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido.")]
[Display(Name = "Stock")]
public int Stock { get; set; }
[Display(Name = "Estado")]
public bool Estado { get; set; }
public int IdCategoria { get; set; }
public int IdProveedor { get; set; }
public String Categoria { get; set; }
public String Proveedor { get; set; }
public String Nombre_Estado { get; set; }
}
}
Ahora creamos el siguiente proyecto llamado Data.
Segunda Capa: Data
Nuestra capa Data tal como ya se dijo en las primeras lineas de esta entrada, tendremos una clase Connection, la estructura de la misma es como sigue:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace Data
{
public class Connection
{
private static Connection _objCnn = null;
private SqlConnection _cnn;
private SqlTransaction _trn;
private Connection()
{
_cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString());
}
public static Connection InitializeConnection()
{
if (_objCnn == null)
{
_objCnn = new Connection();
}
return _objCnn;
}
public SqlConnection getCnn()
{
return _cnn;
}
public SqlConnection OpenConnection()
{
try
{
if (_cnn.State == ConnectionState.Open)
{
return _cnn;
}
else
{
_cnn.Open();
}
return _cnn;
}
catch (Exception)
{
throw;
}
}
public void CloseConnection()
{
try
{
if (_cnn != null && _cnn.State != ConnectionState.Closed)
{
_cnn.Close();
}
}
catch (Exception)
{
throw;
}
}
}
}
Ahora, construimos nuestro
REPOSITORY PATTERN
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data
{
public interface IRepository where T : class
{
bool Insert(T model);
bool Update(T model);
bool Delete(int id);
T GetById(int id);
IEnumerable GetAll();
IEnumerable SearchBy(T model);
}
}
Ok, para finalizar la capa DATA, necesitamos crear una clase la cual implementará la interfaz creada anteriormente. Yo la llamé:
ProductoRepository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Entity;
using System.Data;
using System.Data.SqlClient;
namespace Data
{
public class ProductoRepository : IRepository
{
private Connection _objCnn;
//private SqlCommand _cmd;
private SqlDataReader _reader;
private string _tabla = string.Empty;
public ProductoRepository()
{
_objCnn = Connection.InitializeConnection();
_tabla = "Productos";
}
public bool Delete(int id)
{
int i;
StringBuilder query = new StringBuilder();
query.AppendFormat("DELETE FROM {0} WHERE id=@Id ", _tabla);
try
{
using (SqlCommand cmd = new SqlCommand(query.ToString(), _objCnn.getCnn()))
{
cmd.Parameters.AddWithValue("@id", id);
_objCnn.OpenConnection();
i = cmd.ExecuteNonQuery();
}
}
catch (Exception)
{
throw;
}
finally
{
_objCnn.CloseConnection();
}
return i >= 1;
}
public IEnumerable GetAll()
{
StringBuilder query = new StringBuilder();
query.AppendLine("SELECT p.id, p.nombre, p.descripcion, p.precio_unitario, p.stock, p.id_proveedor, p.id_categoria, p.estado, c.nombre as categoria, v.nombre as proveedor");
query.AppendFormat("FROM {0} p ", _tabla);
query.AppendLine("INNER JOIN Categorias c on c.id=p.id_categoria");
query.AppendLine("INNER JOIN Proveedores v on v.id=p.id_proveedor");
List listaProductos = new List();
try
{
using (SqlCommand cmd = new SqlCommand(query.ToString(), _objCnn.getCnn()))
{
_objCnn.OpenConnection();
_reader = cmd.ExecuteReader();
while (_reader.Read())
{
Producto objProducto = new Producto();
objProducto.Id = Convert.ToInt32(_reader["id"].ToString());
objProducto.Nombre = _reader["nombre"].ToString();
objProducto.Descripcion = _reader["descripcion"].ToString();
objProducto.PrecioUnitario = Convert.ToDouble(_reader["precio_unitario"].ToString());
objProducto.Stock = Convert.ToInt32(_reader["stock"].ToString());
objProducto.IdProveedor = Convert.ToInt32(_reader["id_proveedor"].ToString());
objProducto.IdCategoria = Convert.ToInt32(_reader["id_categoria"].ToString());
objProducto.Estado = Convert.ToBoolean(_reader["estado"].ToString());
objProducto.Categoria = _reader["categoria"].ToString();
objProducto.Proveedor = _reader["proveedor"].ToString();
listaProductos.Add(objProducto);
}
}
}
catch (Exception)
{
//throw;
}
finally
{
_objCnn.CloseConnection();
}
return listaProductos;
}
public Producto GetById(int id)
{
StringBuilder query = new StringBuilder();
query.AppendLine("SELECT p.id, p.nombre, p.descripcion, p.precio_unitario, p.stock, p.id_proveedor, p.id_categoria, p.estado, c.nombre as categoria, v.nombre as proveedor, case p.estado when 1 then 'Activo' else 'Inactivo' end as nombre_estado");
query.AppendFormat("FROM {0} p ", _tabla);
query.AppendLine("INNER JOIN Categorias c on c.id=p.id_categoria");
query.AppendLine("INNER JOIN Proveedores v on v.id=p.id_proveedor");
query.AppendLine("WHERE p.id = @id");
Producto p = new Producto();
try
{
using (SqlCommand cmd = new SqlCommand(query.ToString(), _objCnn.getCnn()))
{
_objCnn.OpenConnection();
cmd.Parameters.AddWithValue("@id", id);
_reader = cmd.ExecuteReader();
if (_reader != null && _reader.HasRows)
{
_reader.Read();
p.Id = Convert.ToInt32(_reader["id"].ToString());
p.Nombre = _reader["nombre"].ToString();
p.Descripcion = _reader["descripcion"].ToString();
p.PrecioUnitario = Convert.ToDouble(_reader["precio_unitario"].ToString());
p.Stock = Convert.ToInt32(_reader["stock"].ToString());
p.IdProveedor = Convert.ToInt32(_reader["id_proveedor"].ToString());
p.IdCategoria = Convert.ToInt32(_reader["id_categoria"].ToString());
p.Estado = Convert.ToBoolean(_reader["estado"].ToString());
p.Categoria = _reader["categoria"].ToString();
p.Proveedor = _reader["proveedor"].ToString();
p.Nombre_Estado = _reader["nombre_estado"].ToString();
}
}
}
catch (Exception)
{
//throw;
}
finally
{
_objCnn.CloseConnection();
}
return p;
}
public bool Insert(Producto model)
{
//string msg = string.Empty;
int i;
StringBuilder query = new StringBuilder();
query.AppendFormat("INSERT INTO {0} ", _tabla);
query.AppendLine("(nombre, descripcion, precio_unitario, stock, id_proveedor, id_categoria, estado)");
query.AppendLine("VALUES");
query.AppendLine("(@nombre, @descripcion, @precio_unitario, @stock, @id_proveedor, @id_categoria, @estado)");
//query.AppendLine(";SELECT SCOPE_IDENTITY()");
try
{
using (SqlCommand cmd = new SqlCommand(query.ToString(), _objCnn.getCnn()))
{
cmd.Parameters.AddWithValue("@nombre", model.Nombre);
cmd.Parameters.AddWithValue("@descripcion", model.Descripcion);
cmd.Parameters.AddWithValue("@precio_unitario", model.PrecioUnitario);
cmd.Parameters.AddWithValue("@stock", model.Stock);
cmd.Parameters.AddWithValue("@id_proveedor", model.IdProveedor);
cmd.Parameters.AddWithValue("@id_categoria", model.IdCategoria);
cmd.Parameters.AddWithValue("@estado", model.Estado);
_objCnn.OpenConnection();
//i = (int)cmd.ExecuteScalar();
i =cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
//msg= ex.Message;
throw new Exception(ex.Message);
}
finally
{
_objCnn.CloseConnection();
}
//return i;
return i >= 1;
}
public IEnumerable SearchBy(Producto model)
{
StringBuilder query = new StringBuilder();
query.AppendLine("SELECT p.id, p.nombre, p.descripcion, p.precio_unitario, p.stock, ");
query.AppendLine("p.id_proveedor, p.id_categoria, p.estado, c.nombre as categoria, v.nombre as proveedor");
query.AppendFormat("FROM {0} p ", _tabla);
query.AppendLine("INNER JOIN Categorias c on c.id=p.id_categoria");
query.AppendLine("INNER JOIN Proveedores v on v.id=p.id_proveedor");
query.AppendLine("WHERE 1=1 and");
if (model.Id > 0)
{
query.AppendLine("p.id=@id");
}
if (model.Nombre != string.Empty)
{
string condicion;
condicion = (model.Id > 0) ? " and p.nombre like '%' + @nombre + '%' " : " p.nombre like '%' + @nombre + '%' ";
query.AppendLine(condicion);
//query.AppendLine("p.nombre like '%' + @nombre + '%' ");
}
List listaProductos = new List();
try
{
using (SqlCommand cmd = new SqlCommand(query.ToString(), _objCnn.getCnn()))
{
_objCnn.OpenConnection();
cmd.Parameters.AddWithValue("@id", model.Id);
cmd.Parameters.AddWithValue("@nombre", model.Nombre);
_reader = cmd.ExecuteReader();
while (_reader.Read())
{
Producto objProducto = new Producto();
objProducto.Id = Convert.ToInt32(_reader["id"].ToString());
objProducto.Nombre = _reader["nombre"].ToString();
objProducto.Descripcion = _reader["descripcion"].ToString();
objProducto.PrecioUnitario = Convert.ToDouble(_reader["precio_unitario"].ToString());
objProducto.Stock = Convert.ToInt32(_reader["stock"].ToString());
objProducto.IdProveedor = Convert.ToInt32(_reader["id_proveedor"].ToString());
objProducto.IdCategoria = Convert.ToInt32(_reader["id_categoria"].ToString());
objProducto.Estado = Convert.ToBoolean(_reader["estado"].ToString());
objProducto.Categoria = _reader["categoria"].ToString();
objProducto.Proveedor = _reader["proveedor"].ToString();
listaProductos.Add(objProducto);
}
}
}
catch (Exception)
{
//throw;
}
finally
{
_objCnn.CloseConnection();
}
return listaProductos;
}
public bool Update(Producto model)
{
int i;
StringBuilder query = new StringBuilder();
query.AppendFormat("UPDATE {0} ", _tabla);
query.AppendLine("SET nombre = @nombre, descripcion = @descripcion, precio_unitario = @precio_unitario, stock = @stock,");
query.AppendLine("id_proveedor = @id_proveedor, id_categoria = @id_categoria, estado = @estado");
query.AppendLine("WHERE id = @id");
try
{
using (SqlCommand cmd = new SqlCommand(query.ToString(), _objCnn.getCnn()))
{
cmd.Parameters.AddWithValue("@nombre", model.Nombre);
cmd.Parameters.AddWithValue("@descripcion", model.Descripcion);
cmd.Parameters.AddWithValue("@precio_unitario", model.PrecioUnitario);
cmd.Parameters.AddWithValue("@stock", model.Stock);
cmd.Parameters.AddWithValue("@id_proveedor", model.IdProveedor);
cmd.Parameters.AddWithValue("@id_categoria", model.IdCategoria);
cmd.Parameters.AddWithValue("@estado", model.Estado);
cmd.Parameters.AddWithValue("@id", model.Id);
_objCnn.OpenConnection();
i = cmd.ExecuteNonQuery();
}
}
catch (Exception)
{
return false;
//throw;
}
finally
{
_objCnn.CloseConnection();
}
return i >= 1;
}
}
}