Introducción

Existen varias formas de consultar datos relacionados en ef core 2.

  • Eager Loading permite consultar a través del método include() del DbSet<T> datos relacionados en la misma consulta. 
  • Las proyecciones de consultas donde es posible ajustar con precisión la forma en la que se van a devolver los datos. Se utiliza el método Select() de linq.
  • Explicit Loading donde ya tenemos datos en memoria y volvemos a ejecutar una consulta para obtener datos relacionados con esos objetos en memoria.
  • Lazy Loading donde se incluyen todos los datos relacionados de un objeto. Esta característica estará disponible en versiones posteriores a ef core 2.

Eager Loading

Vamos a realizar una consulta donde vamos a obtener los vehículos con sus respectivos estacionamientos. Para obtener los estacionamientos, es necesario utilizar el método Include() del DbSet para incluir la colección de estacionamientos del objeto vehículo.

private static void GetVehiclesWithParkingsInclude()
{
    var vehicles = _context.Vehicles.Include(p => p.Parkings).ToList();
}

Los comandos SQL que ejecuta ef core 2 son los siguientes

query_related_data_efCore2
query_related_data_efCore2

Ef core 2 ejecuta dos consultas separadas. Lo hace para evitar obtener datos duplicados. Esta manera es mas eficiente para procesar los resultados en memoria. 

La consulta final devuelve la lista de vehículos con sus respectivos estacionamientos vinculados.

Filtrar un objeto e incluir datos relacionados

Puede existir los casos en que necesitemos obtener un vehículo con una patente en particular y todos sus estacionamientos dentro del sistema. Podríamos utilizar el método FirstOrDefault() e incluir los estacionamientos pero esto es incorrecto porque include() es un metodo del DbSet

var vehicle = _context.Vehicles.FirstOrDefault(p => p.LicensePlate == "NJS981")
                                .Include(p => p.Parkings);

Al querer hacer esto, nos da error

‘Vehicle’ does not contain a definition for ‘Include’ and no extension method ‘Include’ accepting a first argument of type ‘Vehicle’ could be found

Esto es porque Include() no es un método de extensión para FirstOrDefault(). 

Para solucionar esto, debemos ajustar nuestro código de la siguiente manera

private static void GetVehiclesWithParkingsInclude()
{
            //var vehicles = _context.Vehicles.Include(p => p.Parkings).ToList();

            var vehicle = _context.Vehicles.Where(p => p.LicensePlate == "NJS981")
                                            .Include(p => p.Parkings)
                                            .FirstOrDefault();
}

Aplicamos el método include() sobre el DbSet, la condición de la patente la pasamos a la clausula Where() y finalmente aplicamos el FirstOrDefault() sobre la lista.

Proyecciones de consulta – Select()

Para especificar que propiedades queremos obtener en nuestra consulta utilizamos el método Select(). Este método nos permite ajustar nuestra consulta para retornar únicamente las propiedades que vamos a utilizar de ese objeto. Muchas veces, las propiedades que seleccionamos, no coinciden con un objeto en particular, por lo que se define un objeto anónimo utilizando la palabra clave new.

Vamos a realizar una consulta para obtener la lista de vehículos y la cantidad de estacionamientos asociados.

private static void GetVehiclesWithParkingsSelect()
{
    var vehiclesAnonymous = _context.Vehicles.Select(p => new
    {
        p.Id,
        p.LicensePlate,
        p.Parkings.Count
    }).ToList();
}

Estamos asignando una lista de objetos anónimos, donde cada objeto va a tener las 3 propiedades proyectadas en el método Select(). 

El comando SQL que ejecuta ef core 2 es el siguiente

select_linq_efCore2
select_linq_efCore2

Filtrar datos relacionados de un objeto

En ocasiones, necesitamos filtrar los datos relacionados de un objeto y no es necesario retornar los datos relacionados. Veamos como consultar los vehículos que estacionaron entre dos fechas. Debemos filtrar nuestra colección de estacionamientos.

private static void GetVehiclesFilterParkings()
{
    var startDate = DateTime.Today.AddDays(-4);
    var endDay = DateTime.Today;

    var vehicles = _context.Vehicles
                            .Where(p => p.Parkings.Any(x => x.CheckIn >= startDate && x.CheckIn <= endDay))
                            .ToList();
}

El comando SQL que ejecuta ef core 2 es el siguiente

select_between_efCore2
select_between_efCore2

Ef core 2 verifica que vehículos tienen estacionamientos entre dos fechas establecidas como parámetros. En este caso solo retornamos la lista de vehículos sin estacionamientos asociado pero si filtrando sobre ellos.

GITHUB /mpetrinidev

/blog-parking-ef-core-2

Branch [query-filter-related-objects]

¡Si te gusto el articulo, compártelo con tus contactos en las redes sociales!

Escribe una respuesta a este comentario

avatar
500
  Subscribe  
Notificar de