FILTRADO, MULTISELECIÓN Y JOIN
Hasta el momento hemos
visto cómo realizar consultas sencillas sobre una colección, recuperando el
objeto de rango sobre el que iteramos, componentes de éste o un nuevo objeto,
bien de un tipo existente o anónimo. Es lo que se conoce en álgebra relacional
como operaciones de proyección.
En el presente artículo
aprenderemos a realizar operaciones de filtrado a través de la sentencia where.
También reciben el nombre de operaciones de restricción.
Para el siguiente artículo
haremos uso de las clases definidas en el artículo anterior, en el que
devolvíamos la totalidad de los registros de una lista, siendo uno o varios
campos de la entidad. A partir de ahora utilizaremos la sentencia where de
LINQ, que es bastante similar a la que usamos en SQL.
Para filtrar una consulta
en LINQ añadiremos la sentencia where <condición>. La condición, a
diferencia de SQL, deberá utilizar el formato estándar del lenguaje, tal y como
hacemos en una sentencia if o while. Así, si queremos recuperar
aquellos productos cuyo precio sea superior a 7 Euros, lanzaríamos la siguiente
consulta sobre la lista ListaProductos:
1 2 3 |
var productosDeMasDeSieteEuros = from p in DataLists.ListaProductos where p.Precio > 7 select p; |
Simple, ¿verdad? El
resultado sera un único elemento (Mochila escolar).
Al igual que ocurre con las
sentencias if y while, es posible concatenar condiciones. Así,
si queremos recuperar aquellos productos cuyo precio sea mayor de 7 euros o que
cueste entre 3 y 5 euros, construiríamos la siguiente sentencia:
1 2 3 |
var productosDeMasDeSieteEuros = from p in DataLists.ListaProductos where (p.Precio > 7) || ((p.Precio
> 3) && (p.Precio < 5)) select p; |
Vemos que la sintaxis es
sencilla de entender. El resultado será el siguiente:
Como podemos comprobar, la
operación de restricción no tiene mucha complicación. Tan sólo deberemos
aplicar los mismos principios que aplicamos en una sentencia condicional
habitual para obtener aquellos elementos que queramos obtener. Volveremos a
este tema, sin embargo, cuando comprobemos cómo podemos realizar un join entre
dos tablas. Por ahora continuaremos con las Multiselect, operaciones de
proyección sobre más de una tabla.
Multiselección
Hasta ahora hemos
comprendido que una sentencia LINQ es capaz de iterar sobre una colección, realizar
un filtrado y proyectar aquellos elementos resultantes. Sin embargo, es posible
iterar sobre más de un elemento tal y como también es posible anidar
dos o más bucles.
Por ejemplo, si quisiéramos
mostrar a qué cliente pertenece cada pedido, podríamos hacer algo como lo
siguiente:
1 2 3 4 5 6 7 8 9 10 11 |
var listaPedidosClientes = from c in DataLists.ListaClientes
// Lista de clientes from p in DataLists.ListaPedidos
// Lista de pedidos where p.IdCliente ==
c.Id // Filtro: ID del pedido == ID del
cliente select new { NumPedido = p.Id, FechaPedido = p.FechaPedido, NombreCliente =
c.Nombre }; // Recorremos la consulta y
mostramos el resultado foreach (var pedidoCliente in listaPedidosClientes) { Console.WriteLine(String.Format("El
pedido {0} enviado en {1} pertenece a {2}", pedidoCliente.NumPedido,
pedidoCliente.FechaPedido, pedidoCliente.NombreCliente)); } |
Esto proporcionará la
siguiente salida:
Join
Este mismo proceso podría
realizarse de una forma más «natural» mediante un join, tal y como
haríamos en una sentencia SQL.
La sintaxis del INNER
JOIN es también bastante parecida a SQL. Si quisiéramos obtener el
equivalente LINQ a la siguiente sentencia:
1 2 3 |
select P.Id as IdPedido, P.FechaPedido as FechaPedido, C.Nombre as NombreCliente from Clientes C inner join Pedidos P on C.Id = P.IdCliente |
Haríamos algo similar a lo
siguiente:
1 2 3 |
var listaPedidosClientes = from c in DataLists.ListaClientes
// Lista de clientes join p in DataLists.ListaPedidos on c.Id equals p.IdCliente
// Equivale al INNER JOIN TABLA2 ON TABLA1.ID_PK = TABLA2.ID_FK select new { NumPedido = p.Id, FechaPedido =
p.FechaPedido, NombreCliente = c.Nombre }; |
El resultado de esta
sentencia será exactamente igual al anterior:
Como podemos observar, a
poco tiempo que hayamos jugueteado con LINQ, si tenemos un mínimo de
experiencia con SQL, este tipo de sentencias será pan comido.