En Entity Framework las proyecciones nos permiten transformar los datos que obtenemos de una consulta.
Por ejemplo, podemos seleccionar solo las propiedades o campos que nos interesan, cuando trabajamos con entidades complejas que contienen muchas propiedades, pero solo necesitamos un subconjunto de ellas.
Para ello Entity Framework utiliza el método de de LINQ Select
, que es el encargado de realizar estas proyecciones, permitiéndonos definir qué datos queremos recuperar y cómo queremos estructurarlos.
Las proyecciones no solo nos permiten seleccionar solo los datos que necesitamos, sino que también pueden mejoran significativamente el rendimiento.
Realmente modifican la consulta SQL generada. Al reducir la cantidad de datos transferidos desde la base de datos, minimizamos el tiempo de ejecución y el consumo de memoria.
Uso básico de Select
La cláusula Select
se utiliza para proyectar los resultados de una consulta en una nueva forma. Veamos un ejemplo básico:
var nombres = context.Usuarios
.Select(u => u.Nombre)
.ToList();
En este ejemplo,
- Seleccionamos solo la propiedad
Nombre
de la entidadUsuario
- El resultado es una lista de cadenas (
List<string>
) que contiene los nombres de todos los usuarios.
Proyección de múltiples propiedades
Si necesitamos seleccionar más de una propiedad, podemos hacerlo utilizando un tipo anónimo:
var usuarios = context.Usuarios
.Select(u => new
{
u.Nombre,
u.Email
})
.ToList();
Aquí,
- Estamos creando un tipo anónimo que contiene las propiedades
Nombre
yEmail
de cada usuario. - El resultado es una lista de objetos anónimos, cada uno con estas dos propiedades.
Los tipos anónimos son una característica de C# que nos permite crear objetos sin necesidad de definir una clase explícita. Son especialmente útiles en consultas LINQ, donde a menudo necesitamos estructuras de datos temporales
Proyecciones avanzadas
Proyecciones con relaciones entre entidades
Cuando trabajamos con entidades relacionadas, las proyecciones nos permiten incluir datos de entidades relacionadas en nuestros resultados. Por ejemplo:
var pedidos = context.Pedidos
.Select(p => new
{
p.Id,
p.Fecha,
ClienteNombre = p.Cliente.Nombre,
Total = p.Detalles.Sum(d => d.Cantidad * d.Precio)
})
.ToList();
En este ejemplo, estamos seleccionando el ID y la fecha del pedido, junto con el nombre del cliente y el total calculado a partir de los detalles del pedido.
Proyecciones con métodos de extensión
También podemos combinar Select
con otros métodos de LINQ para realizar proyecciones más complejas. Por ejemplo:
var productos = context.Productos
.Where(p => p.Precio > 100)
.Select(p => new
{
p.Nombre,
p.Precio,
Categoria = p.Categoria.Nombre
})
.OrderBy(p => p.Precio)
.ToList();
Aquí, estamos filtrando los productos con un precio mayor a 100, seleccionando el nombre, el precio y la categoría, y ordenando los resultados por precio.
Ejemplos prácticos
Proyección de datos para una vista
Supongamos que estamos desarrollando una aplicación web y necesitamos mostrar una lista de usuarios con su nombre y correo electrónico. Podemos utilizar una proyección para obtener solo los datos necesarios:
var usuarios = context.Usuarios
.Select(u => new
{
u.Nombre,
u.Email
})
.ToList();
Proyección con cálculos
Imaginemos que necesitamos calcular el total de ventas por cliente. Podemos utilizar una proyección para realizar este cálculo directamente en la consulta:
var ventasPorCliente = context.Pedidos
.GroupBy(p => p.Cliente.Nombre)
.Select(g => new
{
Cliente = g.Key,
TotalVentas = g.Sum(p => p.Total)
})
.ToList();
Proyección con datos relacionados
Si necesitamos mostrar una lista de productos junto con su categoría, podemos utilizar una proyección que incluya datos de una entidad relacionada:
var productos = context.Productos
.Select(p => new
{
p.Nombre,
p.Precio,
Categoria = p.Categoria.Nombre
})
.ToList();