Search code examples
c#linqentity-framework-core

Replacing ElementAt in a LINQ query to cover multiple elements


I want to retrieve a list of Orders based on a multiple Location lists.

For context: a Group can have a multiple Locations (one-to-many) and an Order has one Location (many-to-one). I want to get all the Orders of a Group based on the Locations it has.

The following works for the first element in the list of Groups:

List<Order> orders = _context.Orders
    .Where(o => groups.ElementAt(0).Locations.Contains(o.Location))
    .ToList()

I want to change it such that it will not only check the first Group element, but all of them. Help is appreciated.


Solution

  • As groups is only a variable, you can use SelectMany to flatten the nested hierarchy before running the query:

    var locations = groups.SelectMany(x => x.Locations).ToArray();
    

    This basically changes a nested hierarchy

    G1
      L11
      L12
    G2
      L21
      L22
    

    to a flat list of locations:

    L11
    L12
    L21
    L22
    

    After that, you can use the locations in the query:

    List<Order> orders = _context.Orders
      .Where(o => locations.Contains(o.Location))
      .ToList()
    

    If the groups can contain duplicate locations, you could also add a Distinct after the SelectMany.