Mostrando entradas con la etiqueta Expresiones Lambda. Mostrar todas las entradas
Mostrando entradas con la etiqueta Expresiones Lambda. Mostrar todas las entradas

12.30.2012

QueryInterceptors en WCF Data Services

Los QueryInterceptors son atributos que nos permiten personalizar la forma en que se llevan a cabo las consultas utilizando WCF Data Services – aunque en realidad sirven para muchas otras cosas más. Creando un servicio para consumirlo desde un dispositivo móvil utilice estos atributos para llevar a cabo una tarea de consulta de forma sencilla utilizando WCF Data Services y utilizando notación JSON. El escenario lo describo a continuación.

Resulta que tengo un conjunto de registros pero solo necesito los registros que tienen una propiedad especifica seteada con un valor especifico. En WCF Data Services esto implica hacer una consulta en Linq y proceder con el filtro. Sin embargo utilizando los QueryInterceptors ya no es necesario crear la consulta en Linq del lado del cliente y puedo proceder directamente desde el servicio. Para ilustrar este caso vamos a ir con un ejemplo.

Supongamos que tenemos una tabla de películas con todas las películas del año, tal y como se ve en la figura ( datos de ejemplo por supuesto )

image

Ahora bien, resulta que la aplicación móvil solo debe de desplegar las películas que están en cartelera, es decir EnCines = 0. Para llevar a cabo esta tarea, hice un WCF Data Services y le configuré el modelo del Entity Framework para que pueda devolver las entidades. Si no agregamos ningún método o un QueryInterceptor, entonces vamos a poder filtrar utilizando un browser y modificando el query string, o creando un cliente y utilizando Linq. Sin embargo, como ya sabía que requería solo las películas que estaban en el cine proyectándose, procedí a crear un interceptor que me permita devolver solo las películas cuya Propiedad EnCines = 0.

image

Como se ve en la figura anterior, el QueryInterceptor es un atributo que se le aplica al conjunto de registros que se específica en el atributo, en este caso “Películas”. Seguidamente procedemos a crear una Expresión de Linq en donde establecemos que esa expresión recibe Película y retorna un booleano. Luego con una expresión lambda procedemos a aplicar la comparación deseada.

Como vemos en la siguiente figura, la consulta inicial solo nos retorna los registros de las películas que tienen el atributo EnCines = 0.

image

Etiquetas de Technorati: ,

6.28.2012

Implementando un Foreach con expresión Lambda

En días pasados dando una capacitación, le solicité al grupo de desarrolladores que hicieran un método que recibiera una lista de clientes y un parámetro tipo string –> en este caso el país –> para filtrar la lista con este parámetro y retornar otra lista con los clientes que pertenecen al país solicitado. Como era de esperarse, la mayoría de los estudiantes solucionó el problema con un foreach y haciendo una comparación en cada iteración. Sin embargo, creo que es mucho más simple implementar esta solución a través de una expresión lambda y es lo que me llevó a escribir este post.

En primera instancia vamos a escribir la clase cliente sobre la cual vamos a llevar a cabo el procedimiento.

public class Cliente
{
public int Id { get; set; }
public string Nombre { get; set; }
public string Apellido1 { get; set; }
public string Apellido2 { get; set; }
public string Pais { get; set; }
}

Ahora procedemos a escribir el método que recibirá la lista de clientes y procederá a retornar otra lista filtrada con el parámetro número 2 –> el país de donde quiero los clientes.

public List<Cliente> ObtenerPorPais(List<Cliente> pLista, string pPais)
{
return pLista.Where(p => p.Pais == pPais).ToList();
}

En este código se va a comprara cada uno de los elementos de la lista, y los que cumplan con la condición ( p.Pais == pPais) serán retornados en una lista cuyo tipo se infiere a partir del tipo de la lista original y de la invocación del método ToList().


Como podemos ver en el método anterior, es mucho más simple implementar la solución con una expresión lambda y un método de extensión de linq que utilizar un foreach y una comparación por cada elemento de forma manual.



Etiquetas de Technorati: ,,,,

8.06.2011

Tipos Anónimos y Expresiones Lambda

En post pasados hemos hecho consultas utilizando LinqToEntities o LinqToXml y hemos retornado tipos anónimos en cada consulta. En realidad la necesidad de tener un tipo anónimo viene del hecho de que en algunos casos hacemos consultas que dada su estructura se solicitan unos datos de una fuente y otros datos de otra fuente. Por ejemplo, supongamos que tenemos una tabla para Clientes y otra tabla para Órdenes, y queremos hacer una consulta que me devuelva el nombre del cliente, dirección del cliente y el número de cada orden que el cliente posee. En este caso el escenario sería el siguiente:

image

El modelo del EntityFramework para acceder a estas tablas sería el siguiente:

image

Si hacemos la consulta utilizando LinqToEntities esta luciría de la siguiente forma:

image

Como podemos ver, la hacer un join de las dos tablas, no tenemos un tipo que represente el tipo que queremos obtener, por lo tanto debemos crear un tipo anónimo tal y como se ve en la consulta. La pregunta sería: ¿ cómo lograr lo mismo utilizando expresiones Lambda?

La expresión lambda es un poco más abstracta pero nos da el mismo resultado. El código para hacer la consulta anterior con una expresión lambda es el siguiente:

image

Como vemos en el código anterior, utilizamos el método de extensión join y luego le indicamos con que lista de entidades hacer el join, luego sobre cuales campos se hace el join, y por último creamos el tipo anónimo.

Etiquetas de Technorati: ,

1.08.2010

Linq y los Árboles de Expresiones ( Expression Trees) – Parte 1

Los árboles de expresiones nos permiten parsear expresiones enviadas a un método. Un árbol de expresiones en Linq es como lo indica su nombre, una estructura de árbol que contiene expresiones. Las expresiones por otra parte, en este caso particular son expresiones Lambda, las cuales como vimos en un post pasado, son una nueva manera de definir un delegate en C#. El árbol de expresiones es una estructura de datos que contiene expresiones lambda compiladas.

Los árboles de expresiones son dinámicos, ya que al igual que los delegates, permiten cambiar en tiempo de ejecución la expresión a ejecutar; es decir, estos árboles son estructuras que contienen expresiones que se utilizan para procesar los datos. Para entender como funcionan los árboles de expresiones vamos a analizar un ejemplo. En primera instancia, vamos a tener una clase Producto.

public class Producto
{
public int Id { get; set; }
public string Nombre { get; set; }
public double Precio { get; set; }

public Producto(int id, string nombre, double precio)
{
Id = id;
Nombre = nombre;
Precio = precio;
}
}



Seguidamente vamos a crear un arreglo de productos y vamos a aplicarle una expresión lambda utilizando un árbol de expresiones.



private static void ApplyFunction()
{
Producto[] productos = {
new Producto(1, "Laptop", 500),
new Producto(2, "Monitor", 300),
new Producto(3, "Zune HD", 230),
new Producto(4, "IPod Touch", 200),
new Producto(5, "Black Berry Storm", 540),
new Producto(6, "Wii", 199)
};

String Message = "";
Expression<Func<Producto, Boolean>> expProductos = miProducto => miProducto.Precio > 299;
foreach (Producto producto in productos)
if (expProductos.Compile().Invoke(producto))
Message = Message + producto.Nombre + "\r\n";
Console.WriteLine(Message);
}


La parte del árbol de expresiones empieza en la parte de la creación de lo que parece un bloque de código complejo. La clase Expression<T> acepta un delegate prototipo como parámetro. El delegate se define usando el delegate genérico Func<T, TResult>. En este caso, el delegate genérico acepta un string como parámetro de entrada y retorna un booleano.Sin embargo, se pueden utilizar cualquier tipo en la entrada o en el retorno que se requiera en la aplicación. La definición de la expresión viene de seguido, expProductos contiene una expresión booleana que recibe un string y devuelve un booleano, el cual es determinado a partir del precio del producto – si es mayor de 99 retorna true, de lo contrario retorna false. En este punto, expProductos contiene una estructura árbol que incluye todos los elementos requeridos para la expresión lambda: miProducto => miProducto.Precio > 299;



Para invocar la función se invoca la expresión utilizando Compile().Invoke(producto) donde se evalúa la variable que se envía por parámetro y se retorna verdadero si cumple con la expresión, o falso si no lo cumple.



En el siguiente post vamos a crear un árbol de expresiones desde 0.



Technorati Tags: ,,

10.29.2009

Expresiones Lambda en VB.NET 9.0

Explorando un poco las nuevas facilidades del lenguaje VB.NET en el framework 4.0, me encontré con algo que realmente me llamó la atención positivamente: expresiones lambda. Una de las formas de aprovechar las expresiones lambda es utilizandolas en las extensiones de métodos que tienen diversas clases, las cuales nos permiten de forma sencilla realizar operaciones que normalmente tomarían muchas líneas de código. Veamos el siguiente ejemplo:

En versiones anteriores se podía en VB.NET – y también en C# – utilizar la extensión del método FindAll de una lista para obtener una sub lista con todos los ítems que hicieran match con el criterio del predicado enviado por parámetro al método de extensión. El predicado de esta función, por lo general es un delegate que apunta a un método definido en otro lugar, o es un método anónimo. El siguiente código nos muestra esta situación:

image

Como podemos ver en la figura, tenemos una lista de enteros la cual se inicializa de 1 a 10. Seguidamente vamos a crear otra lista de enteros y la vamos a inicializar solamente con los números pares de la lista inicial. Esto lo logramos utilizando un predicado en el método de extensión FindAll de la clase List(Of T ), este predicado contiene la dirección de un método el cual se va a ejecutar por cada ítem contenido en la lista.

Si usamos una expresión lambda, el método será un poco más sencillo de escribir, tal y como podemos ver en el siguiente código:

image

El método anterior funciona de forma idéntica al método en donde utilizamos un delegate, pero no tiene una referencia a otro método que haga la operación deseada, en cambio la expresión lambda escrita como predicado del método FindAll se ejecuta de la misma manera que se ejecuta el delegate a la función ObtenerPares.