jueves, 10 de octubre de 2013

1.3. Mantenimiento de una Tabla de SQL con un Formulario Usando la Clase CDatos

Desarrollando el Mantenimiento de Datos de Una Tabla

Cuando hacemos un programa con base de datos u otra tecnología donde necesitemos guardar los datos de forma persistente, es decir, la guardemos para su posterior uso; necesitamos realizar el mantenimiento de los datos, en este caso haremos como ejemplo el mantenimiento de la tabla de SqlServer denominada tProducto. El mantenimiento consiste en realizar las siguientes operaciones:
  • Insertar registros en la tabla, significa agregar nuevos datos.
  • Modificar registros, con esta operación podemos cambiar los datos ya existentes de un registro, la modificación casi siempre de realiza haciendo referencia al ID del registro.
  • Eliminar registro, realizamos el borrado del registro, normalmente se borra haciendo referencia al ID del registro.
  • Listas y consultas, estas operaciones nos permiten ver los registros grabados en una tabla, aquí pueden hacerse la búsquedas, consultas anidadas, etc.

La base de Datos en SqlServer

Ante de desarrollar un sistema o programa que maneje una base de datos, debemos contar con la base de datos bien diseñada y codificada, es decir, ya debemos tener la base de datos en forma física. Es por esta razón que pongo aquí el código de la base de datos que tu deberás correr en tu gestor SQL Server.


 CÓDIGO DE LA BASE DE DATOS
El siguiente código tiene incluye la creación de la base de datos, la creación de la tabla y las operaciones básicas de mantenimiento como son insertar, modificar, eliminar y algunas consultas necesarias.
 /*Cambiando el formato de fecha a día,mes,año el formato debe coincidir con C#*/
SET DATEFORMAT dmy;
/*Esta base de datos tiene una sola  tabla, es solo un ejemplo*/
use master;
go
drop database bdAlmacen;
go
Create database bdAlmacen;
go
use bdAlmacen;
go
Create Table tProducto
(
idProducto int primary key identity,
nombre varchar(100),
cantidad int,
precio money,
fecFab datetime, --Fecha de fabricación
observacion text
);
go
/*Listar todos los productos*/
select * from tProducto;
/*Insertar registros a la tabla*/
insert into tProducto(nombre, cantidad, precio, fecFab, observacion) values('Monitor LED 18p',7, 125.4, '12/11/2012','N.');
/*Modificar datos del producto*/
update tProducto set nombre='Monitor LCD 15p', cantidad=5, precio=90.5, fecFab='19/05/2008', observacion='S.' where idProducto=1;
/*Eliminar un producto por id*/
--delete from tProducto where idProducto=1;
/*Buscar un producto por su codigo*/
select * from tProducto where idProducto=1;
/*Buscar un producto por nombre*/
select * from tProducto where nombre like '%LCD%';
/*Buscar un producto por Fecha*/
select * from tProducto where fecFab = '19/05/2008';

FinDelCódigo 

La clase CDatos

He construido una clase básica para hacer la conexión de SqlServer con C#, esta clase tiene dos métodos principales, estos son:

Método EjecutarComando

Lo usaremos para ejecutar ordenes Sql desde C#, la característica de las ordenes es que debe ser de tipo comando, es decir, no devolver datos, por ejemplo esto son:

  • insert
  • update
  • delete
  • procedimientos almacenados que no devuelven datos.

Método EjecutarConsulta

También lo usamos para ejecutar una orden Sql desde C#, las ordenes a ejecutar con este metodo son de tipo consultas, significa que devuelven datos, estas ordenes son:
  • select
  • procedimientos almacenados que devuelven datos de tipo select.
Esta clase puede ser reutilizada y/o mejorada para otros proyectos.

  CÓDIGO DE LA CLASE CDatos.cs
Para entender esta clase deberás leer los comentarios ya que estos indican para que usamos cada orden, he querido hacer la clase más simple posible ya que el objetivo de esto es que se pueda entender sin complicaciones de ningún tipo como se usan los comandos, la clase y como esta estructurado.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
//AppProducto, Este es el nombre de la aplicación, deberás cambiarlo si usas otro nombre
namespace AppProducto
{
    public class CDatos
    {
        //Aquí esta la cadena de conexión a SqlServer, dependiendo de tu proyecto, esto debes cambiarlo
        //normalmente se cambia el nombre del servidor y el nombre de la base de datos
        string cadenaDeConexion = @"Data Source=(local);Initial Catalog=bdAlmacen;Integrated Security=True";

        public string EjecutarComando(string textoSql)
        {
            //Para la cadena de conexión
            string sCnn = cadenaDeConexion;
            //Creamos la conexión
            SqlConnection cnn = new SqlConnection(sCnn);
            //Texto del comando insert
            string iTexto = textoSql;
            //Creamos el comando con su texto y conexión
            SqlCommand cmd = new SqlCommand(iTexto, cnn);
            cmd.CommandType = CommandType.Text;
            //abrimos la conexión y ejecutamos el comando
            cnn.Open();
            //Ejecutamos el comando sql
            cmd.ExecuteNonQuery();
            //Cerramos la conexión
            cnn.Close();
            return "Comando realizado con exito...";
        }

        public DataTable EjecutarConsulta(string textoSQL)
        {
            //Creamos la cadena de conexion
            string sCnn = cadenaDeConexion;
            //Creamo el comando de sql para listar
            string sSel = textoSQL;
            //Creamos el adaptador que capturara los datos
            SqlDataAdapter da = new SqlDataAdapter(sSel, sCnn);
            //Creamos un data table que contendra los datos
            DataTable dt = new DataTable();
            //Llenamos el data table con el adaptador
            da.Fill(dt);
            //Colocando datos al datagridview dgvNacionalidad
            return dt;
        }
    }
}
FinDelCódigo 

La Clase CProducto

Para poder realizar las operaciones de mantenimiento, vamos ha desarrollar la siguiente clase, esta clase representa la unión entre el C# y el SqlServer, es la clase de transición, en este caso usaremos lar ordenes Sql directamente.

Algo importante a tener en cuenta es que esta clase presenta una herencia, la clase padre es CDatos, por tanto esta clase cuenta con los métodos de su clase padre que son: EjecutarComando y EjecutarConsulta.

Nota que los campos y propiedades de la clase escrita en C# son los mismos que los campos que tenemos en la tabla tProducto de la base de datos. En sistemas grandes casi siempre se hace una clase por cada tabla de la base de datos donde coinciden los campos de la tabla con los de la clase en C# u otro lenguaje que uses.

 CÓDIGO DE LA CLASE CProducto.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace AppProducto
{
    class CProducto : CDatos
    {
        /*Aqui todos los campos deben coincidir con la base de datos*/
        int idProducto;

        public int IdProducto
        {
            get { return idProducto; }
            set { idProducto = value; }
        }
        string nombre;

        public string Nombre
        {
            get { return nombre; }
            set { nombre = value; }
        }
        int cantidad;

        public int Cantidad
        {
            get { return cantidad; }
            set { cantidad = value; }
        }
        double precio;

        public double Precio
        {
            get { return precio; }
            set { precio = value; }
        }
        DateTime fecFab;

        public DateTime FecFab
        {
            get { return fecFab; }
            set { fecFab = value; }
        }
        string observacion;

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

        /*Metodos de la clase, segun las necesidades de la aplicacion*/
        /*Los siguientes metodos no retornan datos, es decir no son consultas*/
        public string Insertar()
        {
            string texto = "insert into tProducto(nombre, cantidad, precio, fecFab, observacion) values('" + Nombre + "'," + Cantidad + ", " + Precio + ", '" + FecFab.ToString("d/M/yyyy HH:mm:ss") + "','" + Observacion + "');";
            return EjecutarComando(texto);
        }
        public string Modificar()
        {
            string texto = "update tProducto set nombre='" + Nombre + "', cantidad=" + Cantidad + ", precio=" + Precio + ", fecFab='" + FecFab.ToString("d/M/yyyy") + "', observacion='" + Observacion + "' where idProducto=" + IdProducto + ";";
            return EjecutarComando(texto);
        }
        public string Eliminar()
        {
            string texto = "delete from tProducto where idProducto="+IdProducto+";";
            return EjecutarComando(texto);
        }
        /*Estos metodos retornan resultados pues con consultas*/
        public DataTable Listar()
        {
            string texto = "select * from tProducto;";
            return EjecutarConsulta(texto);
        }
        public DataTable ListarPorIdProducto()
        {
            string texto = "select * from tProducto where idProducto="+IdProducto+";";
            return EjecutarConsulta(texto);
        }
        public DataTable ListarPorNombre()
        {
            string texto = "select * from tProducto where nombre like '%" + Nombre + "%';";
            return EjecutarConsulta(texto);
        }
        public DataTable ListarPorFecha()
        {
            string texto = "select * from tProducto where fecFab = '" + FecFab.ToString("d/M/yyyy") + "';";
            return EjecutarConsulta(texto);
        }
    }
}

FinDelCódigo 

Nota Importante
En la clase usamos las ordenes de Sql, insert, update, delete, select estas están ensambladas usando las propiedades de la clase CPersona, tambien puedes observar el uso de los metodos EjecutarComando y EjecutarConsulta.

El formulario

El siguiente formulario deberá ser diseñado con sus nombres correspondientes y los controles definidos. Esta es la interfaz de usuario con la cual aquel que use la aplicación se va ha comunicar, en nuestro caso este formulario tiene las operaciones básicas de mantenimiento y consulta.


Este formulario presenta los siguientes controles:
  • txtIdProducto, es un control de tipo TextBox
  • txtNombre, es un control de tipo TextBox
  • txtCantidad, es un control de tipo TextBox
  • txtPrecio, es un control de tipo TextBox
  • txtObservacion, es un control de tipo TextBox, propiedad MultiLine en true
  • dtpFecha, es un control de tipo DateTimePicker
  • dgvDatos, es un control de tipo DataGridView, prodiedad ReadLine en true
  • btnInsertar, es un control de tipo Button
  • btnModificar, es un control de tipo Button 
  • btnEliminar, es un control de tipo Button
  • btnListar, es un control de tipo Button
  • btnBuscarId, es un control de tipo Button
  • btnBuscarNombre, es un control de tipo Button
  • Los controles de tipo Label, no tienen nombres pues no los hemos usado como parte del código.

Propiedades Desarrolladas en el Formulario

En este formulario hemos agregado una propiedad llamada oProducto, que es la instancia de la clase CPersona, ahora una vez que tenemos el objeto oProducto ya podemos usarlo en todo el formulario, el siguiente es el código para crear el objeto:


CODIGO PARA CREAR EL OBJETO oProducto
         /* Código Nuevo: Creando el objeto de tipo CProducto */
        CProducto oProducto = new CProducto();

FinDelCódigo 


En la figura siguiente te muestro como debe quedar este código en la aplicación general.

Figura Nº 1.

Métodos Codificados en el Formulario

Método LlenarObjeto()

Cuando usas controles, en estos puedes ingresar datos, estos datos al final son lo que se trabajan, es por ello que necesitamos un metodo LlenarObjeto que permitirá vaciar los datos que tienes en el formulario a el objeto oProducto, luego de esto tu podrás hacer las operaciones que necesites ya que los datos ya los tiene el objeto.

Importante
Ver la figura Nº1 para observar como debe quedar el código LlenarObjeto en tu formulario.

Código del Método LlenarObjeto
         /* Código Nuevo: Llenar el objeto con datos, este metodo hace que los de los controles pasen al objeto*/
        public bool LlenarObjeto()
        {
            try
            {
                try { oProducto.IdProducto = int.Parse(txtIdProducto.Text); }
                catch { oProducto.IdProducto = 0; }
                oProducto.Nombre = txtNombre.Text;
                oProducto.Observacion = txtObservacion.Text;
                oProducto.Precio = double.Parse(txtPrecio.Text);
                oProducto.FecFab = dtpFecha.Value;
                return true;//Devuelve verdadero cuando los datos son correctos
            }
            catch
            {
                return false;//Devuelve falso cuando los datos NO son correctos
            }
        }

FinDelCódigo 


Código de los Controles

Los controles del formulario necesitan código, en nuestro caso el código de todos los controles manipulan las operaciones del objeto oProducto.

 CÓDIGO DEL BOTÓN 
btnInsertar
         private void btnInsertar_Click(object sender, EventArgs e)
        {
            //Usando el Metodo de Formulario LlenarObjeto
            if (LlenarObjeto())
            {
                //Usando el metodo Insertar de oProducto
                MessageBox.Show(oProducto.Insertar());
                //Borrando los datos del DataGridView
                dgvDatos.DataSource = null;
            }
            else
            {
                //Mensaje en caso de error al llenar el objeto
                MessageBox.Show("Error al llenar los datos...");
            }
        }

FinDelCódigo 


CÓDIGO DEL BOTÓN 
btnModificar
         private void btnModificar_Click(object sender, EventArgs e)
        {
            //Usando el Metodo de Formulario LlenarObjeto
            if (LlenarObjeto())
            {
                //Ejecutar el metodo Modificar de oProducto
                MessageBox.Show(oProducto.Modificar());
                //Borrando los datos del DataGridView
                dgvDatos.DataSource = null;
            }
            else
            {
                MessageBox.Show("Error al llenar los datos...");
            }
        }

FinDelCódigo 


 CÓDIGO DEL BOTÓN 
btnEliminar
         private void btnEliminar_Click(object sender, EventArgs e)
        {
            try
            {
                //Asignando el Id del control al objeto oProducto
                oProducto.IdProducto = int.Parse(txtIdProducto.Text);
                //Ejecutando el método Eliminar de oProducto
                MessageBox.Show(oProducto.Eliminar());
                //Borrando los datos del DataGridView
                dgvDatos.DataSource = null;
            }
            catch
            {
                //Mostrando mensaje de error
                MessageBox.Show("Error Debes proporcionar el ID");
            }
        }

FinDelCódigo 


CÓDIGO DEL BOTÓN 
btnListar
         private void btnListar_Click(object sender, EventArgs e)
        {
            //Usando el metodo Listar de oProducto y mostrandolo en el DataGridView
            dgvDatos.DataSource = oProducto.Listar();
        }

FinDelCódigo 


 CÓDIGO DEL BOTÓN 
btnBuscarId
         private void btnBuscarId_Click(object sender, EventArgs e)
        {
            try
            {
                //Proporcionamos el Id al objeto oProducto
                oProducto.IdProducto = int.Parse(txtIdProducto.Text);
                //Ejecutamos el metodo ListarPorIdProducto
                dgvDatos.DataSource = oProducto.ListarPorIdProducto();
            }
            catch
            {
                //Mensaje de error
                MessageBox.Show("Falta Ingresar el ID");
            }
        }

FinDelCódigo 


CÓDIGO DEL BOTÓN 
btnBuscarNombre
         private void btnBuscarNombre_Click(object sender, EventArgs e)
        {
            try
            {
                //Proporcionamos el Nombre al objeto
                oProducto.Nombre = txtNombre.Text;
                //Ejecutamos el metodo ListarPorNombre
                dgvDatos.DataSource = oProducto.ListarPorNombre();
            }
            catch
            {
                //Mensaje de error
                MessageBox.Show("Falta Ingresar el Nombre");
            }
        }

FinDelCódigo 


 CÓDIGO DEL DATAGRIDVIEW (dgvDatos)
EVENTO CellClick
         /*Metodo CellClick del DataGridView, cuando hacemos clic en el DataGridView*/
        private void dgvDatos_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                //Pasando los datos del DataGridView a los Controles
                txtIdProducto.Text = dgvDatos.CurrentRow.Cells[0].Value.ToString();
                txtNombre.Text = dgvDatos.CurrentRow.Cells[1].Value.ToString();
                txtCantidad.Text = dgvDatos.CurrentRow.Cells[2].Value.ToString();
                txtPrecio.Text = dgvDatos.CurrentRow.Cells[3].Value.ToString();
                dtpFecha.Value = DateTime.Parse(dgvDatos.CurrentRow.Cells[4].Value.ToString());
                txtObservacion.Text = dgvDatos.CurrentRow.Cells[5].Value.ToString();
            }
            catch
            {
                MessageBox.Show("Posible error por falta de datos....");
            }
        }

FinDelCódigo 

Importante Anotaciones sobre ADO.NET Usadas en la Clase CDatos

ADO.NET

Es un conjunto de clases que exponen servicios de acceso a datos para el programador de .NET. ADO.NET ofrece abundancia de componentes para la creación de aplicaciones de uso compartido de datos distribuidas. Constituye una parte integral de .NET Framework y proporciona acceso a datos relacionales, XML y de aplicaciones. ADO.NET satisface diversas necesidades de desarrollo, como la creación de clientes de base de datos de aplicaciones para usuario y objetos empresariales de nivel medio que utilizan aplicaciones, herramientas, lenguajes o exploradores de Internet.

Algunas Clases de ADO NET

SqlConnection (Clase)

Su espacio de nombres es System.Data.SqlClient, representa una conexión abierta con una base de datos de SQL Server. Esta clase no se puede heredar.

Un objeto SqlConnection representa una única sesión con un origen de datos de SQL Server. Con un sistema de bases de datos de cliente y servidor, equivale a una conexión de red al servidor. SqlConnection se utiliza junto con SqlDataAdapter y SqlCommand para aumentar el rendimiento de la conexión a una base de datos de Microsoft SQL Server.

SqlDataAdapter (Clase)

Pertenece al espacio de nombres System.Data.SqlClient, representa un conjunto de comandos de datos y una conexión de base de datos que se utilizan para rellenar un DataSet y actualizar una base de datos de SQL Server. Esta clase no se puede heredar.

SqlDataAdapter, se utiliza como un puente entre DataSet y SQL Server para recuperar y guardar datos. SqlDataAdapter proporciona este puente mediante la asignación de Fill, que cambia los datos en DataSet para que coincidan con los datos del origen de datos; y Update, que cambia los datos en el origen de datos para que coincidan con los datos en DataSet utilizando las instrucciones de Transact-SQL en el origen de datos adecuado.




4 comentarios:

  1. ES UNA INTERFAZ VIRTUAL...SIRVE COMO PUENTE PARA EL FORMULARIO CLASE

    ResponderEliminar
  2. como hago un inser toamdo un egisro de un toamdo la colunda de un datagrid em c#
    dgv.Cells[0].Value.ToString()
    lo hago asi y me da error

    ResponderEliminar
  3. waooo, excelente material. me servirá como referencia para poder corregirme, muchas gracias por este gran aporte ingeniero.

    ResponderEliminar