9.12.2009

Extendiendo el Entity Framework – Comparación y Búsqueda de Entidades

Una de las tareas más comunes cuando trabajamos con el Entity Framework es la búsqueda de las entidades en una lista y la comparación de las mismas. El EF nos provee la facilidad de agregar código para comparación a través de la Interface IEquatable y las clases parciales.

Interface IEquatable<T>

La interface IEquatable<T> de acuerdo al msdn se define como una interface que define un metodo de igualdad, el cual determina la igualdad de las instancias del tipo implementado. Por otro lado y para aclarar por adelantado, la Interface IComparable<T> define un metodo de comparación generalizado para ordenamiento de instancias.

IEquatable<T> se usa normalmente por colecciones genericas tales como List<T> y LinkedList<T> para ser utilizado en métodos tales como Contains, IndexOf, Remove, etc. Esta interface se debe de implementar en cualquier objeto que se va a almacenar en colecciones genéricas.

Extendiendo una Entidad con IEquatable<T>

El primer paso para extender una entidad del Entity Framework es crear una clase que contenga este código adicional. En este caso, vamos a extender la entidad Empresa y por lo tanto, vamos a crear una clase parcial que igualmente se va a llamar empresa. Para esto procedemos a agregar la clase en el proyecto donde definimos el modelo del Entity Framework.

imageSeguidamente procedemos a poner la clase recién creada como pública y parcial; esto va a permitir que esta clase se compile en conjunto con la clase generada por el EF en una sola clase,  por lo que toda la funcionalidad que agregemos a esta clase será parte de la clase Empresa del EF. Además, por estar en una clase parcial, si tenemos que regenerar el modelo, no vamos a perder la lógica incluída.

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

namespace Samples
{
public partial class Empresa
{
}
}
Como podemos ver en la siguiente figura, la clase que genera el EF es también parcial y por lo tanto podemos agregar la funcionalidad que deseamos.


image Seguidamente procedemos a implementar la clase IEquatable<T> para poder definir como vamos a hacer las comparaciones en nuestra entidad. Nótese como el método definido en el contrato de la interface – Equals – recibe otra entidad de tipo empresa para llevar a cabo la comparación.



public partial class Empresa : IEquatable<Empresa>
{
#region IEquatable<Empresa> Members

public bool Equals(Empresa other)
{
//Aquí vamos a implementar nuestra comparación
return true;
}

#endregion
}



Para este caso especifico, quiero que la empresa se pueda comparar tanto por el campo Id como por el nombre, es decir, buscarla en la lista por nombre y buscarla por Id para cuando por ejemplo el item se selecciona desde un combo box.



public partial class Empresa : IEquatable<Empresa>
{
#region IEquatable<Empresa> Members

public bool Equals(Empresa other)
{
if (this.Id == other.Id || this.Nombre == other.Nombre)
return true;
return false;
}

#endregion
}



Como podemos ver, el método Equals contiene la definición de comparación que nosotros creamos conveniente para poder utilizar la entidad en nuestra lógica de negocios.



Ahora vamos a utilizar nuestra entidad para diferentes propósitos. Inicialmente vamos a tener una pantalla para buscar empresas por nombre tal y como luce a continuación.



image La idea es buscar entre las empresas del grid la que deseamos y desplegarla en un diálogo modal. Este dialogo que se presentará de forma modal es el siguiente:



imageEl siguiente paso es crear la lógica para presentar un detalle de una empresa en el dialogo anterior, lo cual hacemos con el siguiente código:



public partial class frmEmpresa : Window
{
private Empresa m_Empresa;

public Empresa EmpresaProp
{
get { return m_Empresa; }
set { m_Empresa = value; }
}

public frmEmpresa(Empresa pEmpresa)
{
InitializeComponent();
EmpresaProp = pEmpresa;
txtNombre.Text = EmpresaProp.Nombre;
txtDireccion.Text = EmpresaProp.Direccion;
txtTelefono.Text = EmpresaProp.Telefono;
txtEmail.Text = EmpresaProp.Email;
}

public frmEmpresa()
{
InitializeComponent();
}

private void btnCerrar_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}


Ahora vamos a programar el código necesario para buscar la entidad deseada en la lista que hemos cargado en el grid y si la encontramos, procedemos a invocar la forma anterior para presentar su detalle.



public partial class BuscarEmpresa : Window
{
List<Empresa> m_Empresas = new List<Empresa>();

public List<Empresa> Empresas
{
get { return m_Empresas; }
set { m_Empresas = value; }
}
public BuscarEmpresa()
{
InitializeComponent();
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
Empresas = ObtenerEmpresas();
dgEmpresas.ItemsSource = Empresas;

}

public List<Empresa> ObtenerEmpresas()
{
UseCasesEntities entities = new UseCasesEntities();
var Empresas = from e in entities.Empresa select e;
return Empresas.ToList();
}

private void btnBuscar_Click(object sender, RoutedEventArgs e)
{
Empresa empresaTmp = new Empresa();
empresaTmp.Nombre = txtEmpresa.Text;

if (Empresas.Contains(empresaTmp))
{

frmEmpresa frm = new frmEmpresa(Empresas[Empresas.IndexOf(empresaTmp)]);
frm.ShowDialog();
}
else
MessageBox.Show("Empresa no existe", "Mensaje");
}
}



El código que nos interesa es el código del evento click del botón buscar. Lo primero que hacemos es crear una instancia de la entidad empresa y proceder a asignarle el valor digitado por el usuario en el textbox. Seguidamente, vamos a pedirle a la lista de empresas ( declarada al inicio de la clase ) a través del método Contains, si tiene una entidad igual a la que le estoy enviando. Nótese que aunque no he cargado todos los campos, el llamado a Contains busca la implementación de la interface IEquatable<T> para hacer la búsqueda, por esta razón si digitamos el nombre de alguna empresa que exista, el método lo encuentra. Si el existe, el siguiente paso es desplegarlo en la pantalla de detalle pasándola por parámetro. Para lograr esta funcionalidad tenemos que ir a obtener la entidad de la lista, lo cual se logra con una combinación de un método de la lista – IndexOf - y el indexador de la misma []. IndexOf utiliza la comparación que nos provee la interface IEquatable<T>. El resultado al ejecutar el ejemplo anterior es el siguiente:



imageEn los post siguientes vamos a profundizar en este tema.













No hay comentarios: