Saltar al contenido

Filtrar por incluir en EF Core

Haz todo lo posible por comprender el código bien antes de aplicarlo a tu proyecto y si ttienes algo que aportar puedes comentarlo.

Solución:

Entity Framework core 5 es la primera versión de EF que admite filtrado Include.

Cómo funciona

Operaciones admitidas:

  • Where
  • OrderBy(Descending)/ThenBy(Descending)
  • Skip
  • Take

Algunos ejemplos de uso (de la solicitud de función original y el commmit de github):

Solo se permite un filtro por navegación, por lo que en los casos en los que la misma navegación debe incluirse varias veces (por ejemplo, múltiples ThenInclude en la misma navegación), aplique el filtro solo una vez o aplique exactamente el mismo filtro para esa navegación.

context.Customers
    .Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.OrderDetails)
    .Include(c => c.Orders).ThenInclude(o => o.Customer)

o

context.Customers
    .Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.OrderDetails)
    .Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.Customer)

Otra nota importante:

Las colecciones incluidas mediante nuevas operaciones de filtrado se consideran cargadas.

Eso significa que si la carga diferida está habilitada, abordar el problema de un cliente Orders colección del último ejemplo no activará una recarga de todo el Orders colección.

Además, dos posteriores filtrados Includes en el mismo contexto acumularán los resultados. Por ejemplo…

context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))

…seguido por…

context.Customers.Include(c => c.Orders.Where(o => o.IsDeleted))

…resultará en customers con Orders colecciones que contienen todos los pedidos.

Corrección de inclusión y relación filtrada

Si otro Orders se cargan en el mismo contexto, es posible que se agreguen más a un customers.Orders colección debido a arreglo de la relación. Esto es inevitable debido a cómo funciona el rastreador de cambios de EF.

context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))

…seguido por…

context.Orders.Where(o => o.IsDeleted).Load();

… resultará de nuevo en customers con Orders colecciones que contienen todos los pedidos.

Filtrado Include vs filtrar la consulta

Filtrado Include ha dado lugar a cierta confusión sobre cómo afecta el filtrado de una consulta en su conjunto. La regla general es: no es así.

La declaración…

context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))

…devoluciones todo clientes del contexto, no solo los que tienen pedidos no eliminados. El filtro en el Include no afecta la cantidad de elementos devueltos por la consulta principal.

Por otro lado, la declaración …

context.Customers
    .Where(c => c.Orders.Any(o => !o.IsDeleted))
    .Include(c => c.Orders)

… solo devuelve a los clientes que tienen al menos un pedido sin eliminar, pero que tienen todo de sus órdenes en el Orders colecciones. El filtro de la consulta principal no afecta a los pedidos por cliente devueltos por Include.

Para obtener clientes con pedidos no eliminados y que solo carguen sus pedidos no eliminados, se requieren dos filtros:

context.Customers
    .Where(c => c.Orders.Any(o => !o.IsDeleted))
    .Include(c => c.Orders.Where(o => !o.IsDeleted))

No factible.

Hay una discusión en curso sobre este tema: https://github.com/aspnet/EntityFramework/issues/1833

Sugeriría buscar cualquiera de las bibliotecas de terceros enumeradas allí, por ejemplo: https://github.com/jbogard/EntityFramework.Filters

También puede invertir la búsqueda.


    var blogs = context.Author
    .Include(author => author.posts)
        .ThenInclude(posts => posts.blogs)
    .Where(author => author == "me")
    .Select(author => author.posts.blogs)
    .ToList();

Ten en cuenta dar visibilidad a este post si si solucionó tu problema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *