miércoles, 22 de enero de 2014

DESKTOP APPLICATION - 2º Parte - Sistema de Ventas C# - Base de datos SQL

1. Entorno


  • SQL Server 2008
  • Visual Studio 2008

2. Introducción


2.1. Programación por capas

La programación por capas es un estilo de programación en el que el objetivo primordial es la separación de la lógica de negocios de la lógica de diseño. La ventaja principal de este estilo es que el desarrollo se puede llevar a cabo en varios niveles y, en caso de que sobrevenga algún cambio, sólo se ataca al nivel requerido sin tener que revisar entre código mezclado. Un buen ejemplo de este método de programación sería el modelo de interconexión de sistemas abiertos

2.2. Programación en tres capas

  • Capa de presentación: es la que ve el usuario (también se la denomina "capa de usuario"), presenta el sistema al usuario, le comunica la información y captura la información del usuario en un mínimo de proceso (realiza un filtrado previo para comprobar que no hay errores de formato). Esta capa se comunica únicamente con la capa de negocio. También es conocida como interfaz gráfica y debe tener la característica de ser "amigable" (entendible y fácil de usar) para el usuario.
  • Capa de negocio: es donde residen los programas que se ejecutan, se reciben las peticiones del usuario y se envían las respuestas tras el proceso. Se denomina capa de negocio (e incluso de lógica del negocio) porque es aquí donde se establecen todas las reglas que deben cumplirse. Esta capa se comunica con la capa de presentación, para recibir las solicitudes y presentar los resultados, y con la capa de datos, para solicitar al gestor de base de datos para almacenar o recuperar datos de él. También se consideran aquí los programas de aplicación.
  • Capa de datos: es donde residen los datos y es la encargada de acceder a los mismos. Está formada por uno o más gestores de bases de datos que realizan todo el almacenamiento de datos, reciben solicitudes de almacenamiento o recuperación de información desde la capa de negocio.

3. Desarrollo


3.1. Creando el proyecto

Primero debemos de crear un proyecto con Visual Studio 2008, para eso abrimos el Visual Studio 2008 y nos vamos al menú de "Archivo-->Nuevo Proyecto". A nuestro proyecto le pondremos de nombre "SistemaVentas"

3.2. Agregando la Capa de Datos

Debemos de agregar a nuestro proyecto la capa de datos, para eso nos vamos al menu de "Archivo-->Agregar Nuevo Proyecto"


Y le pondremos como nombre "CapaDatos"


3.3. La clase Conexion

Para agregar una clase en C# debemos hacer clic derecho en la Capa de Datos y seleccionar la opción "Agregar-->Clase" y la clase que creamos se llamara "Conexion", que se encargara de guardar la cadena de conexión para poder conectarnos con nuestra base de datos que esta en SQL Server 2008 y la cual se llama BDTutorial.
























La clase Conexion tendrá el siguiente código en C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//Desarrollado por Adrián Sánchez

namespace CapaDatos
{
  public class Conexion
  {
    //La base de datos se llama BDTutorial
    //La ubicacion de base de datos esta de modo local y en una instancia que se llama SQL2008
    //Utiliza seguridad integrada para conectarse a la base de datos
    public static string cn = "Data Source=.\\SQL2008;Initial Catalog=BDTutorial;Integrated Security=True";
  }
}

3.2. La clase Producto

Esta clase se encarga de conectar la tabla Producto con C#

using System;
using System.Collections.Generic;
using System.Text;
//Impotaciones necesarias
using System.Data;
using System.Data.SqlClient;

//Desarrollado por Adrián Sánchez

namespace CapaDatos
{

  public class Producto
  {
    private int var_codigoProducto;
    private string var_nombre;
    private decimal var_precio;

    //Constructor vacio
    public Producto()
    {

    }

    //Constructor con parametros
    public Producto(
    int codigoProducto,
    string nombre,
    decimal precio
    )
    {
      this.var_codigoProducto = codigoProducto;
      this.var_nombre = nombre;
      this.var_precio = precio;
    }

    //Metodo utilizado para insertar un Producto
    public string Insertar(Producto varProducto)
    {
      string rpta = "";
      SqlConnection sqlCon = new SqlConnection();
      try
      {
        //1. Establecer la cadena de conexion
        sqlCon.ConnectionString = Conexion.cn;
        //2. Abrir la conexion de la BD
        sqlCon.Open();
        //3. Establecer el comando
        SqlCommand sqlCmd = new SqlCommand();
        sqlCmd.Connection = sqlCon;
        sqlCmd.CommandText = "spI_Producto";
        sqlCmd.CommandType = CommandType.StoredProcedure;

        //4. Agregar los parametros al comando
        //Establecemos los valores para el parametro @codigoProducto del Procedimiento Almacenado
        SqlParameter sqlParcodigoProducto = new SqlParameter();
        sqlParcodigoProducto.ParameterName = "@codigoProducto";
        sqlParcodigoProducto.SqlDbType = SqlDbType.Int;
        //Le declaramos que el parametro es de salida, porque obtendremos el codigo generado por la base de datos
        sqlParcodigoProducto.Direction = ParameterDirection.Output;
        sqlCmd.Parameters.Add(sqlParcodigoProducto); //Agregamos el parametro al comando
        //Establecemos los valores para el parametro @nombre del Procedimiento Almacenado
        SqlParameter sqlParnombre = new SqlParameter();
        sqlParnombre.ParameterName = "@nombre";
        sqlParnombre.SqlDbType = SqlDbType.VarChar;
        sqlParnombre.Size = 100;
        sqlParnombre.Value = varProducto.nombre;
        sqlCmd.Parameters.Add(sqlParnombre); //Agregamos el parametro al comando
        //Establecemos los valores para el parametro @precio del Procedimiento Almacenado
        SqlParameter sqlParprecio = new SqlParameter();
        sqlParprecio.ParameterName = "@precio";
        sqlParprecio.SqlDbType = SqlDbType.Decimal;
        sqlParprecio.Precision=18;
        sqlParprecio.Scale=2;
        sqlParprecio.Value = varProducto.precio;
        sqlCmd.Parameters.Add(sqlParprecio); //Agregamos el parametro al comando

        //5. Ejecutamos el commando
        rpta = sqlCmd.ExecuteNonQuery() == 1 ? "OK" : "No se inserto el producto de forma correcta";

      }
      catch (Exception ex)
      {
        rpta = ex.Message;
      }
      finally
      {
        //6. Cerramos la conexion con la BD
        if (sqlCon.State == ConnectionState.Open) sqlCon.Close();
      }
      return rpta;                
    }


    //Metodo utilizado para actualizar un Producto
    public string Actualizar(Producto varProducto)
    {
      string rpta = "";
      SqlConnection sqlCon = new SqlConnection();
      try
      {
        //1. Establecer la cadena de conexion
        sqlCon.ConnectionString = Conexion.cn;
        //2. Abrir la conexion de la BD
        sqlCon.Open();
        //3. Establecer el comando
        SqlCommand sqlCmd = new SqlCommand();
        sqlCmd.Connection = sqlCon;
        sqlCmd.CommandText = "spU_Producto";
        sqlCmd.CommandType = CommandType.StoredProcedure;

        //4. Agregar los parametros al comando
        //Establecemos los valores para el parametro @codigoProducto del Procedimiento Almacenado
        SqlParameter sqlParcodigoProducto = new SqlParameter();
        sqlParcodigoProducto.ParameterName = "@codigoProducto";
        sqlParcodigoProducto.SqlDbType = SqlDbType.Int;
        sqlParcodigoProducto.Value = varProducto.codigoProducto;
        sqlCmd.Parameters.Add(sqlParcodigoProducto); //Agregamos el parametro al comando
        //Establecemos los valores para el parametro @nombre del Procedimiento Almacenado
        SqlParameter sqlParnombre = new SqlParameter();
        sqlParnombre.ParameterName = "@nombre";
        sqlParnombre.SqlDbType = SqlDbType.VarChar;
        sqlParnombre.Size = 100;
        sqlParnombre.Value = varProducto.nombre;
        sqlCmd.Parameters.Add(sqlParnombre); //Agregamos el parametro al comando
        //Establecemos los valores para el parametro @precio del Procedimiento Almacenado
        SqlParameter sqlParprecio = new SqlParameter();
        sqlParprecio.ParameterName = "@precio";
        sqlParprecio.SqlDbType = SqlDbType.Decimal;
        sqlParprecio.Precision = 18;
        sqlParprecio.Scale = 2;
        sqlParprecio.Value = varProducto.precio;
        sqlCmd.Parameters.Add(sqlParprecio); //Agregamos el parametro al comando

        //5. Ejecutamos el commando
        rpta = sqlCmd.ExecuteNonQuery() == 1 ? "OK" : "No se actualizo el producto de forma correcta";

      }
      catch (Exception ex)
      {
        rpta = ex.Message;
      }
      finally
      {
        //6. Cerramos la conexion con la BD
        if (sqlCon.State == ConnectionState.Open) sqlCon.Close();
      }
      return rpta;                
    }

    //Metodo utilizado para obtener todos los productos de la base de datos
    public DataTable ObtenerProducto()
    {
      DataTable dtProducto = new DataTable("Producto");
      SqlConnection sqlCon = new SqlConnection();
      try
      {
        //1. Establecer la cadena de conexion
        sqlCon.ConnectionString = Conexion.cn;

        //2. Establecer el comando
        SqlCommand sqlCmd = new SqlCommand();
        sqlCmd.Connection = sqlCon;//La conexion que va a usar el comando
        sqlCmd.CommandText = "spF_Producto_All";//El comando a ejecutar
        sqlCmd.CommandType = CommandType.StoredProcedure;//Decirle al comando que va a ejecutar una sentencia SQL

        //3. No hay parametros

        //4. El DataAdapter que va a ejecutar el comando y es el encargado de llena el DataTable
        SqlDataAdapter sqlDat = new SqlDataAdapter(sqlCmd);
        sqlDat.Fill(dtProducto);//Llenamos el DataTable
      }
      catch (Exception ex)
      {
        dtProducto = null;
      }
      return dtProducto;
    }

    #region Metodos Get y Set
    public int codigoProducto
    {
      get { return var_codigoProducto; }
      set { var_codigoProducto = value; }
    }
    public string nombre
    {
      get { return var_nombre; }
      set { var_nombre = value; }
    }
    public decimal precio
    {
      get { return var_precio; }
      set { var_precio = value; }
    }
    #endregion

  }
}

3.3. Clase DetalleVenta

Esta clase se encarga de conectar la tabla DetalleVenta con C#

using System;
using System.Collections.Generic;
using System.Text;
//Impotaciones necesarias
using System.Data;
using System.Data.SqlClient;

//Desarrollado por Adrián Sánchez

namespace CapaDatos
{
  public class DetalleVenta
  {
    private int var_codigoVenta;
    private int var_codigoProducto;
    private decimal var_cantidad;
    private decimal var_descuento;

    //Constructor vacio
    public DetalleVenta()
    {

    }

    //Constructor con parametros
    public DetalleVenta(
    int codigoVenta ,
    int codigoProducto ,
    decimal cantidad ,
    decimal descuento 
    )
    {
      this.var_codigoVenta=codigoVenta;
      this.var_codigoProducto=codigoProducto;
      this.var_cantidad=cantidad;
      this.var_descuento=descuento;
    }

    //Metodo utilizado para insertar un DetalleVenta
    //Le pasamos la conexion y la transaccion por referencia, debido a que esos datos lo obtenemos
    //de la clase Venta y no deberiamos crear una nueva Conexion o una nueva Transaccion
    //sino la creada por la clase Venta
    public string Insertar(DetalleVenta varDetalleVenta, ref SqlConnection sqlCon, ref SqlTransaction sqlTra)
    {
      string rpta = "";
      try
      {
        //1. Establecer el comando
        SqlCommand sqlCmd = new SqlCommand();
        sqlCmd.Connection = sqlCon;
        sqlCmd.Transaction = sqlTra;
        sqlCmd.CommandText = "spI_DetalleVenta";
        sqlCmd.CommandType = CommandType.StoredProcedure;

        //4. Agregar los parametros al comando
        //Establecemos los valores para el parametro @codigoVenta del Procedimiento Almacenado
        SqlParameter sqlParcodigoVenta = new SqlParameter();
        sqlParcodigoVenta.ParameterName = "@codigoVenta";
        sqlParcodigoVenta.SqlDbType = SqlDbType.Int;
        sqlParcodigoVenta.Value = varDetalleVenta.codigoVenta;
        sqlCmd.Parameters.Add(sqlParcodigoVenta); //Agregamos el parametro al comando
        //Establecemos los valores para el parametro @codigoProducto del Procedimiento Almacenado
        SqlParameter sqlParcodigoProducto = new SqlParameter();
        sqlParcodigoProducto.ParameterName = "@codigoProducto";
        sqlParcodigoProducto.SqlDbType = SqlDbType.Int;
        sqlParcodigoProducto.Size = 4;
        sqlParcodigoProducto.Value = varDetalleVenta.codigoProducto;
        sqlCmd.Parameters.Add(sqlParcodigoProducto); //Agregamos el parametro al comando
        //Establecemos los valores para el parametro @cantidad del Procedimiento Almacenado
        SqlParameter sqlParcantidad = new SqlParameter();
        sqlParcantidad.ParameterName = "@cantidad";
        sqlParcantidad.SqlDbType = SqlDbType.Decimal;
        sqlParcantidad.Precision = 18;
        sqlParcantidad.Scale = 2;
        sqlParcantidad.Value = varDetalleVenta.cantidad;
        sqlCmd.Parameters.Add(sqlParcantidad); //Agregamos el parametro al comando
        //Establecemos los valores para el parametro @descuento del Procedimiento Almacenado
        SqlParameter sqlPardescuento = new SqlParameter();
        sqlPardescuento.ParameterName = "@descuento";
        sqlPardescuento.SqlDbType = SqlDbType.Decimal;
        sqlParcantidad.Precision = 18;
        sqlParcantidad.Scale = 2;
        sqlPardescuento.Value = varDetalleVenta.descuento;
        sqlCmd.Parameters.Add(sqlPardescuento); //Agregamos el parametro al comando

        //5. Ejecutamos el commando
        rpta = sqlCmd.ExecuteNonQuery() == 1 ? "OK" : "No se inserto el detalle de venta de forma correcta";

      }
      catch (Exception ex)
      {
        rpta = ex.Message;
      }
      return rpta;                
    }

    #region Metodos Get y Set
    public int codigoVenta
    {
      get { return var_codigoVenta; }
      set { var_codigoVenta = value; }
    }
    public int codigoProducto
    {
      get { return var_codigoProducto; }
      set { var_codigoProducto = value; }
    }
    public decimal cantidad
    {
      get { return var_cantidad; }
      set { var_cantidad = value; }
    }
    public decimal descuento
    {
      get { return var_descuento; }
      set { var_descuento = value; }
    }
    #endregion

  }
}

3.4. Clase Venta

Esta clase se encarga de conectar la tabla Venta con C#

using System;
using System.Collections.Generic;
using System.Text;
//Impotaciones necesarias
using System.Data;
using System.Data.SqlClient;

//Desarrollado por Adrián Sánchez

namespace CapaDatos
{
  public class Venta
  {
    private int var_codigoVenta;
    private string var_cliente;
    private DateTime var_fecha;

    //Constructor vacio
    public Venta()
    {

    }

    //Constructor con parametros
    public Venta(int codigoVenta,string cliente,DateTime fecha)
    {
      this.var_codigoVenta=codigoVenta;
      this.var_cliente=cliente;
      this.var_fecha=fecha;
    }

    //Metodo utilizado para insertar un Venta
    public string Insertar(Venta varVenta, List<DetalleVenta> detalles)
    {
      string rpta = "";
      SqlConnection sqlCon = new SqlConnection();

      try
      {
        //1. Establecer la cadena de conexion
        sqlCon.ConnectionString = Conexion.cn;
        //2. Abrir la conexion de la BD
        sqlCon.Open();
        //3. Establecer la transaccion
        SqlTransaction sqlTra = sqlCon.BeginTransaction();
        //4. Establecer el comando
        SqlCommand sqlCmd = new SqlCommand();
        sqlCmd.Connection = sqlCon;
        sqlCmd.Transaction = sqlTra;
        sqlCmd.CommandText = "spI_Venta";
        sqlCmd.CommandType = CommandType.StoredProcedure;
        //5. Agregar los parametros al comando
        //Establecemos los valores para el parametro @codigoVenta del Procedimiento Almacenado
        SqlParameter sqlParcodigoVenta = new SqlParameter();
        sqlParcodigoVenta.ParameterName = "@codigoVenta";
        sqlParcodigoVenta.SqlDbType = SqlDbType.Int;
        sqlParcodigoVenta.Direction = ParameterDirection.Output;
        sqlCmd.Parameters.Add(sqlParcodigoVenta); //Agregamos el parametro al comando
        //Establecemos los valores para el parametro @cliente del Procedimiento Almacenado
        SqlParameter sqlParcliente = new SqlParameter();
        sqlParcliente.ParameterName = "@cliente";
        sqlParcliente.SqlDbType = SqlDbType.VarChar;
        sqlParcliente.Size = 100;
        sqlParcliente.Value = varVenta.cliente;
        sqlCmd.Parameters.Add(sqlParcliente); //Agregamos el parametro al comando
        //6. Ejecutamos el commando
        rpta = sqlCmd.ExecuteNonQuery() == 1 ? "OK" : "No se inserto el detalle de venta de forma correcta";
        if (rpta.Equals("OK"))
        {
          //Obtenemos el codigo de la venta que se genero por la base de datos
          this.codigoVenta=Convert.ToInt32(sqlCmd.Parameters["@codigoVenta"].Value);
          foreach(DetalleVenta det in detalles){
            //Establecemos el codigo de la venta que se autogenero
            det.codigoVenta = this.codigoVenta;
            //Llamamos al metodo insertar de la clase DetalleVenta
            //y le pasamos la conexion y la transaccion que debe de usar
            rpta = det.Insertar(det, ref sqlCon, ref sqlTra);
            if (!rpta.Equals("OK"))
            {
              //Si ocurre un error al insertar un detalle de venta salimos del for
              break;
            }
          }
        }
        if (rpta.Equals("OK"))
        {
          //Se inserto todo los detalles y confirmamos la transaccion
          sqlTra.Commit();
        }
        else
        {
          //Algun detalle no se inserto y negamos la transaccion
          sqlTra.Rollback();
        }

      }
      catch (Exception ex)
      {
        rpta = ex.Message;
      }
      finally
      {
        //6. Cerramos la conexion con la BD
        if (sqlCon.State == ConnectionState.Open) sqlCon.Close();
      }
      return rpta;                
    }

    //Obtenemos la venta por el codigo generado
    public DataTable ObtenerVenta(int codigoVenta)
    {
      DataTable dtVenta = new DataTable("Venta");
      SqlConnection sqlCon = new SqlConnection();
      try
      {
        //1. Establecer la cadena de conexion
        sqlCon.ConnectionString = Conexion.cn;

        //2. Establecer el comando
        SqlCommand sqlCmd = new SqlCommand();
        sqlCmd.Connection = sqlCon;//La conexion que va a usar el comando
        sqlCmd.CommandText = "spF_Venta_One";//El comando a ejecutar
        sqlCmd.CommandType = CommandType.StoredProcedure;//Decirle al comando que va a ejecutar una sentencia SQL

        //3. Agregar los parametros al comando
        //Establecemos los valores para el parametro @codigoVenta del Procedimiento Almacenado
        SqlParameter sqlParcodigoVenta = new SqlParameter();
        sqlParcodigoVenta.ParameterName = "@codigoVenta";
        sqlParcodigoVenta.SqlDbType = SqlDbType.Int;
        sqlParcodigoVenta.Value = codigoVenta;
        sqlCmd.Parameters.Add(sqlParcodigoVenta); //Agregamos el parametro al comando

        //4. El DataAdapter que va a ejecutar el comando y es el encargado de llena el DataTable
        SqlDataAdapter sqlDat = new SqlDataAdapter(sqlCmd);
        sqlDat.Fill(dtVenta);//Llenamos el DataTable
      }
      catch (Exception ex)
      {
        dtVenta = null;
      }
      return dtVenta;
    }

    //Obtener todas las ventas
    public DataTable ObtenerVenta()
    {
      DataTable dtVenta = new DataTable("Venta");
      SqlConnection sqlCon = new SqlConnection();
      try
      {
        //1. Establecer la cadena de conexion
        sqlCon.ConnectionString = Conexion.cn;

        //2. Establecer el comando
        SqlCommand sqlCmd = new SqlCommand();
        sqlCmd.Connection = sqlCon;//La conexion que va a usar el comando
        sqlCmd.CommandText = "spF_Venta_All";//El comando a ejecutar
        sqlCmd.CommandType = CommandType.StoredProcedure;//Decirle al comando que va a ejecutar una sentencia SQL

        //3. No hay parametros

        //4. El DataAdapter que va a ejecutar el comando y es el encargado de llena el DataTable
        SqlDataAdapter sqlDat = new SqlDataAdapter(sqlCmd);
        sqlDat.Fill(dtVenta);//Llenamos el DataTable
      }
      catch (Exception ex)
      {
        dtVenta = null;
      }
      return dtVenta;
    }

    #region Metodos Get y Set
    public int codigoVenta
    {
      get { return var_codigoVenta; }
      set { var_codigoVenta = value; }
    }
    public string cliente
    {
      get { return var_cliente; }
      set { var_cliente = value; }
    }
    public DateTime fecha
    {
      get { return var_fecha; }
      set { var_fecha = value; }
    }
    #endregion

  }
}

4. Resumen


Al final deberíamos tener las siguientes clases

No hay comentarios.:

Publicar un comentario