domingo, 22 de agosto de 2010

Un vistazo a LinqToSql

Hola, ahora quisiera compartir con ustedes como hacer una aplicacion usando LinQ to Sql, bueno, para eso necesitamos Visual Studio 2008 o 2010 y ademas tener un conocimiento minimo de algunas operaciones usando LinQ. En fin abrimos y creamos un proyecto, en este caso yo cree un proyecto de winForms, pero da igual, una vez creado el proyecto, agregamos un nuevo elemento, buscamos clase de linq to sql, que es un archivo de extension dbml, le damos un nombre y aceptamos.
 Bueno, como se daran cuenta se abrira el archivo que llamamos GeneralDC, bueno le puse DC al final para abreviar DataContext que es un contexto de datos. Bueno ahora vamos a nuestro explorador de servidores, en el cual ya deberiamos haber creado una conexion, luego abrimos nuestra base de datos, expandimos la carpeta tablas, seleccionamos las tablas y las arrastramos a la primera columna de GeneralDC.dbml en este caso. Una vez hecho esto, deberiamos tener algo similar:
 Como podremos ver, tenemos una representacion de nuestra base de datos, pero esta vez ademas de ser una representacion relacional, por detras tenemos la representacion orientada a objetos.



Si vemos en el explorador de soluciones, y expandimos el archivo GeneralDC, veremos algo como esto:
 ahora si abrimos el archivo GeneralDC.designer.cs veremos varias lineas de codigo las cuales representan nuestro contexto de datos, pero si lo revisamos con mas detalle, podremos observar que se crearon clases que representan a nuestras entidades, y ademas las relacionan pero esta no es una relacion referencial si no es una relacion pero vista desde programacion orientada a objetos:
[Table(Name="dbo.ItemsVenta")]
public partial class ItemVenta : INotifyPropertyChanging, INotifyPropertyChanged

[Table(Name="dbo.Productos")]
public partial class Producto : INotifyPropertyChanging, INotifyPropertyChanged

[Table(Name="dbo.Ventas")]
public partial class Venta : INotifyPropertyChanging, INotifyPropertyChanged 
Hay que notar que las entidades estan representadas como clases abastractas, entonces si quisieramos agregar metodos a estas clases simplemente creamos estas clases con el mismo nombre, pero debe llevar partial adelante del nombre, por razones de simplicidad simplemente adicionare los metodos ToString() a todas las clases:
public partial class Producto
{
 public override string ToString()
 {
  return this.Descripcion + " - " + this.Precio;
 }
}
public partial class Venta
{
 public override string ToString()
 {
  return this.Fecha;
 }
}
public partial class ItemVenta
{
 public override string ToString()
 {
  return "< " + this.Producto.Descripcion + " >" +
   "< " + this.Venta.Fecha + " >< " + this.Cantidad + " >";
 }
}
Ahora, tradicionalmente para adicionar un registro en una tabla, se suele escribir una sentecia sql de insercion, lo mismo para seleccionar o borrar, etc. pero al crear nuestro contexto de datos esto ya se creo. Bueno para realizar altas, bajas y modificaciones crearemos una clase para cada entidad que realize estas cosas. Un ejemplo seria todo el acceso a datos de la entidad producto, entonces seria algo parecido a esto:


/*
* EL ACCESO A DATOS PARA LA ENTIDAD PRODUCTO TENEMOS LO SIGUIENTE:
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.ComponentModel;
using System.Data.Linq.SqlClient;

namespace ProyectoLinqToSql
{
    public class ProductoAccesoDatos
    {
        private GeneralDCDataContext dc;

        public ProductoAccesoDatos()
        {
            dc = new GeneralDCDataContext();
        }
        public BindingList LinqToList(IQueryable query)
        {
            BindingList lista = new BindingList();
            foreach (T item in query)
            {
                lista.Add(item);
            }
            return lista;            
        }
        public  BindingList ObtenerProductos()
        {   
            IQueryable query = from prod in dc.Producto select prod;
            return LinqToList(query);
        }
        public BindingList ObtenerPorDescripcion(string descripcion)
        { 
            IQueryable query = from prod in dc.Producto where SqlMethods.Like(prod.Descripcion, string.Format("%{0}%", descripcion)) select prod;
            return LinqToList(query);
        }
        public void AdicionarProducto(Producto producto)
        {
            dc.Producto.InsertOnSubmit(producto);
            dc.SubmitChanges();
        }
        public void EliminarProducto(Producto producto)
        {
            dc.Producto.Attach(producto);
            dc.Producto.DeleteOnSubmit(producto);
            dc.SubmitChanges();
        }
        public void ActualizaProducto(Producto original, Producto nuevo)
        {
            dc.Producto.Attach(nuevo, original);
            dc.SubmitChanges();
        }
    }
}
/*
* EL ACCESO A DATOS PARA LA ENTIDAD VENTA TENEMOS LO SIGUIENTE:
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.ComponentModel;

namespace ProyectoLinqToSql
{
    public class VentaAccesoDatos
    {
        private GeneralDCDataContext dc;

        public VentaAccesoDatos()
        {
            dc = new GeneralDCDataContext();
        }
        public BindingList LinqToList(IQueryable query)
        {
            BindingList lista = new BindingList();
            foreach (T item in query)
            {
                lista.Add(item);
            }
            return lista;            
        }
        public BindingList ObtenerVentas()
        {
            IQueryable query = from venta in dc.Venta select venta;
            return LinqToList(query);
        }
        public void AdicionarVenta(Venta venta)
        {
            dc.Venta.InsertOnSubmit(venta);
            dc.SubmitChanges();
        }
        public void EliminarVenta(Venta venta)
        {
            dc.Venta.Attach(venta);
            dc.Venta.DeleteOnSubmit(venta);
            dc.SubmitChanges();
        }
        public void ActualizarVenta(Venta original, Venta nuevo)
        {
            dc.Venta.Attach(nuevo, original);
            dc.SubmitChanges();
        }
    }
}
/*
* EL ACCESO A DATOS PARA LA ENTIDAD ITEMVENTA TENEMOS LO SIGUIENTE:
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.ComponentModel;

namespace ProyectoLinqToSql
{
    public class ItemVentaAccesoDatos
    {
        private GeneralDCDataContext dc;

        public ItemVentaAccesoDatos()
        {
            dc = new GeneralDCDataContext();
        }
        public BindingList LinqToList(IQueryable query)
        {
            BindingList lista = new BindingList();
            foreach (T item in query)
            {
                lista.Add(item);
            }
            return lista;            
        }
        public BindingList ObtenerItemVenta(bool conProducto, bool conVenta)
        {            
            if (conProducto || conVenta)
            {
                DataLoadOptions loadOptions = new DataLoadOptions();
                loadOptions.LoadWith(iv => iv.Producto);
                if (conVenta)
                    loadOptions.LoadWith(iv => iv.Venta);
                dc.LoadOptions = loadOptions;
            }
            IQueryable query = from iv in dc.ItemVenta select iv;
            return LinqToList(query);
        }
        public void AdicionarItemVenta(ItemVenta itemVenta)
        {
            dc.ItemVenta.InsertOnSubmit(itemVenta);
            dc.SubmitChanges();
        }
        public void EliminarItemVenta(ItemVenta itemVenta)
        {
            dc.ItemVenta.Attach(itemVenta);
            dc.ItemVenta.DeleteOnSubmit(itemVenta);
            dc.SubmitChanges();
        }
        public void ActualizarItemVenta(ItemVenta original, ItemVenta nuevo)
        {
            dc.ItemVenta.Attach(nuevo, original);
            dc.SubmitChanges();
        }
    }
}

Los metodos Attach, SubmitChanges, DeleteOnSubmit, InsertOnSubmit son metodos que de alguna forma se comportan como los datasets, pero, por ejemplo con el metodo Attach, le indicamos a nuestro DataContext que ese objeto que pasemos por el metodo Attach estara siendo a ser procesado, bien sea para adicionarlo modificarlo o eliminarlo.
Bueno, las clases anteriores como los comentarios indican, son las clases para el acceso a datos de cada entidad. Bueno pero si este contexto de datos no le parece apropiado, simplemente deberia cambiar, quitar o adicionar codigo al archivo GeneralDC.designer.cs, ya que simplemente la informacion mas importante esta en las clases que representan a las entidades. Ahora para mostrar la manera de llamar esto desde winforms será la sgte., supongamos que tenemos un formulario con este diseño:
ahora el codigo del evento click del boton será de la sgte manera:
private void btnBuscar_Click(object sender, EventArgs e)
{
 ProductoAccesoDatos pad = new ProductoAccesoDatos();
 dgvProducto.DataSource = pad.ObtenerPorDescripcion(txtDescripcion.Text);
}
Ahora si queremos añadir un Producto, supongamos que tenemos un formulario como el siguiente:
y el codigo del evento click del boton será de la sgte manera:
private void btnAdicionar_Click(object sender, EventArgs e)
{
 ProductoAccesoDatos pad = new ProductoAccesoDatos();
 
 Producto prod = new Producto();
 prod.Codigo = Convert.ToInt32(txtCodigo.Text);
 prod.Descripcion = txtDescripcion.Text;
 prod.Precio = Convert.ToFloat(txtPrecio.Text);
 
 pad.AdicionarProducto(prod);
}


Obviamente, el metodo de arriba no muestra las mejores practicas, ya que no realizamos ninguna validacion o establecer patrones de validacion o simplemente añadir una excepcion, en fin esa seria la forma a grandes rasgos de realizar aplicaciones usando LinqToSql.

Bueno creo que eso es todo, espero que les haya sido de utilidad.
Saludos.

No hay comentarios:

Publicar un comentario