In my last two post (
post 1 and
post 2) we saw how to work with Select Clause in LINQ and what projections are all about, but there is one more useful Method called
SelectMany which comes very handy while working with collections within a complex type (in other words to get the flattened result from collection with a type), we will discuss about the SelectMany method with an example in this post and see the major difference between both of them.
SelectMany
Projects each element of a sequence to an IEnumerable and flattens the resulting sequences into one sequence. (definition from
MSDN)
Reading just the definition didn’t actually gave me any clue on how it work, hence lets take our same example which we are working for
past couple of posts)
To recollect, here is the custom class (Student)
public class Student
{
public int StudID { get; set; }
public string Name { get; set; }
public string Class { get; set; }
public List Subjects { get; set; }
}
Here is the list of students
//Create some students
List students = new List()
{
new Student { StudID = 101, Name= "Karthik", Class = "10th", Subjects = new List { "C#", "ADO.Net", "EF"}},
new Student { StudID = 108, Name= "Karthik", Class = "10th", Subjects = new List { "C#", "ADO.Net", "EF"}},
new Student { StudID = 104, Name = "Ram", Class = "11th", Subjects= new List{ ".Net", "C#", "SQL", "EF"}},
new Student { StudID = 103, Name = "John", Class = "9th", Subjects= new List{ ".Net", "MVC"}},
new Student { StudID = 106, Name = "Bill", Class = "9th", Subjects= new List{ "EF", "MVC"}},
};
Now our job is to select all the
Subjects from each student and display them.
Lets first do that using
Select clause
//Select all the subjects from the students
var studentColl = from student in students
select new { student.Subjects};
Console.WriteLine("Select All Subjects using SELECT");
foreach (var stud in studentColl)
{
foreach (var item in stud.Subjects)
{
Console.Write(item);
Console.Write(",");
}
}
As you can see from the above code, I have Selected the subjects from the students collection, since the subject is of IEnumerable (it has list of subjects), I am iterating through each and every subjects and getting the subjects in next foreach loop and displaying the same.
Lets do the same using
SelectMany method
//Using SelectMany
Console.WriteLine("\nSelect All Subjects using SELECTMANY");
var subjectMany = students.SelectMany(x => x.Subjects);
foreach (var item in subjectMany)
{
Console.Write(item);
Console.Write(",");
}
As you can see from the above code, we have just used SelectMany and selected the subjects and as you can see we have only
One foreach loop to access retrieve all the subjects, and the reason is simple, as discussed earlier, the SelectMany method
will flattens the resulting sequences into one sequence.
We can also select the distinct subjects from SelectMany result as shown below
//Select Distinct Subjects
Console.WriteLine("\nSelect only Distinct Subjects");
var subjectDistinct = students.SelectMany(x => x.Subjects).Distinct();
foreach (var item in subjectDistinct)
{
Console.Write(item);
Console.Write(",");
}
Here is the complete code followed by the output
public static void SelectAndSelectManyLINQ()
{
//Create some students
List students = new List()
{
new Student { StudID = 101, Name= "Karthik", Class = "10th", Subjects = new List { "C#", "ADO.Net", "EF"}},
new Student { StudID = 108, Name= "Karthik", Class = "10th", Subjects = new List { "C#", "ADO.Net", "EF"}},
new Student { StudID = 104, Name = "Ram", Class = "11th", Subjects= new List{ ".Net", "C#", "SQL", "EF"}},
new Student { StudID = 103, Name = "John", Class = "9th", Subjects= new List{ ".Net", "MVC"}},
new Student { StudID = 106, Name = "Bill", Class = "9th", Subjects= new List{ "EF", "MVC"}},
};
//Select all the subjects from the students
var studentColl = from student in students
select new { student.Subjects};
Console.WriteLine("Select All Subjects using SELECT");
foreach (var stud in studentColl)
{
foreach (var item in stud.Subjects)
{
Console.Write(item);
Console.Write(",");
}
}
Console.WriteLine("\n");
//Using SelectMany
Console.WriteLine("\nSelect All Subjects using SELECTMANY");
var subjectMany = students.SelectMany(x => x.Subjects);
foreach (var item in subjectMany)
{
Console.Write(item);
Console.Write(",");
}
Console.WriteLine("\n");
//Select Distinct Subjects
Console.WriteLine("\nSelect only Distinct Subjects");
var subjectDistinct = students.SelectMany(x => x.Subjects).Distinct();
foreach (var item in subjectDistinct)
{
Console.Write(item);
Console.Write(",");
}
}
Output
Please leave your comments.
Thanks,
Karthik KK