Published on

Flattening Collections using SelectMany() in EF Core

Authors

Flattening Collections in EF Core: Understanding the Impact of SelectMany on Your LINQ Queries

In Entity Framework Core, the SelectMany operation is used to flatten collections. This can sometimes lead to unexpected results if not used carefully. Let’s illustrate this with an example.

Consider a scenario where we have a list of Students and each Student is enrolled in multiple Courses. We want to retrieve a list of all Active courses that Active students are enrolled in.

Here’s how you might initially write the query:

var activeCourses = await _studentRepository
    .GetAllStudents()
    .Where(student => student.IsActive)
    .SelectMany(student => student.Courses)
    .Where(course => course.IsActive)
    .ToListAsync();

In this query, the Where clause before SelectMany filters the Students, not the Courses. It filters the Students based on the condition specified (i.e., student.IsActive). However, once you use SelectMany, you’re now working with a collection of Courses from all the Students that passed the filter. Any Where clause after SelectMany is applied to this flattened collection of Courses, not the Students. That’s why you might see Courses from Students who are not Active — because the Where clause for the Courses is independent of the Where clause for the Students.

To ensure that you’re only getting Courses from Students who are Active, you need to apply the Courses filter inside the SelectMany. Here’s how you can revise the query:

var activeCourses = await _studentRepository
    .GetAllStudents()
    .Where(student => student.IsActive)
    .SelectMany(student => student.Courses.Where(course => course.IsActive))
    .ToListAsync();

In this revised query, the Courses filter is applied to each Student before the collections are flattened, ensuring that you’re only getting Courses from Students who are Active. Understanding the behavior of SelectMany is crucial when working with LINQ in Entity Framework Core, as it can significantly impact the results of your queries.

I hope this helps! Let me know if you have any other questions.