LINQ SelectMany Method
When objects contain properties which hold a collection of objects, using the Select method is not applicable as it will return a “collection of collections” rather than all the items from those collection properties. We need to use the SelectMany method. The functionality of a SelectMany method is similar to a query expression with multiple from clauses. Let’s say we have a class named Company, and it has a property named Employees which holds a collection of Employee type objects. A collection of Company objects can then be created. By using Select method, we can only query each company as seen below:
var result = comp.Select(c => c);
What if we want to access or retrieve all of the employees for every company and flatten the result as a one whole list of items. Let’s take a look at the following example:
class Company
{
public string CompanyName { get; set; }
public IEnumerable<Employee> Employees { get; set; }
}
class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
class Program
{
public static void Main(string[] args)
{
//Create some sample comp with employees
List<Company> comp = new List<Company>
{
new Company
{
CompanyName = "Company 1",
Employees = new List<Employee>
{
new Employee { FirstName = "John", LastName = "Smith" },
new Employee { FirstName = "Mark", LastName = "Halls" },
new Employee { FirstName = "Morgan", LastName = "Jones" }
}
},
new Company
{
CompanyName = "Company 2",
Employees = new List<Employee>
{
new Employee { FirstName = "Winston", LastName = "Mars" },
new Employee { FirstName = "Homer", LastName = "Saxton" },
new Employee { FirstName = "Creg", LastName = "Lexon" }
}
},
new Company
{
CompanyName = "Company 3",
Employees = new List<Employee>
{
new Employee { FirstName = "Ben", LastName = "Greenland" },
new Employee { FirstName = "Anthony", LastName = "Waterfield" }
}
}
};
//Get All the FirstName of all employees
var firstNames = comp.SelectMany(c=>c.Employees).Select(e=>e.FirstName);
var lastNames = comp.SelectMany(c => c.Employees, (c, e) => e.LastName);
Console.WriteLine("FirstNames of all employees from the three comp.");
foreach (var firstName in firstNames)
Console.WriteLine(firstName);
Console.WriteLine("
LastNames of all the employees from the three comp.");
foreach (var lastName in lastNames)
Console.WriteLine(lastName);
}
}
Example 1 – Using the SelectMany Method
FirstNames of all employees from the threecomp
. John Mark Morgan Winston Homer Creg Ben Anthony LastNames of all the employees from the threecomp
.............
We have defined two classes for this example. The first one named Company contains two properties named CompanyName and Employees. The Employees property has a type of IEnumerable<Employee> which simply means that it allows you to store a collection of Employee objects to it. The Employee class was defined and has two simple properties to define a single employee. In the Main method, we created a collection of Company objects and initialize it to have three Company objects. Each Company objects was set a value for their CompanyName and a collection of Employee objects for their Employees property. Note that we are using the collection and object initializers here.
Lines 52 to 54 uses the SelectMany method. Line 52 queries the FirstNames of all the employees from all the comp
.
comp.SelectMany(c => c.Employees).Select(e => e.FirstName);
This adaptation of SelectMany method acknowledges only one contention. We pass a lambda determining the property that the SelectMany will select. As the name of the method implies, “select many” means the method will select a collection of objects.In our example on top of, we tend to chosen the Employees property of each company that contains a group of Employees. The SelectMany method can currently come back an IEnumerable <Employee>. this permits America to nest another decision to a plain Select technique within which, we tend to chosen the primary name of each worker from the results of the SelectMany method.
There is another version of the SelectMany method which accepts two arguments, a collectionSelector and a resultSelector. If we are to rewrite line 52 using this different version of SelectMany, it will look like this.
comp.SelectMany(c => c.Employees, (c, e) => e.FirstName);
Notice that we don’t need to use the Select method to select a specific property of every Employee. The second argument handles that. The second argument accepts a lambda with two arguments. The first is the current item from the original collection, and the second is the current item from the selected property of the collectionSelector.