Question

I normally use the lambda notation for choice but get frustrated with joins. I set myself a simple exercise using LINQPad. The LINQ query is:

List<int> allStudents = new List<int> {1,2,3,4,5,6,7,8,9};
List <int> studentsIdList = new List<int> {1,3,5,7,9};

var q = 
        from c in allStudents 
        join p in studentsIdList on c equals p into ps 
        from p in ps.DefaultIfEmpty() 
        where p == 0
        select new { Student = c}; 


q.Dump();

which produces the expected result set 2,4,6,8.

HOWEVER, when I write it in lambda notation as:

List<int> allStudents = new List<int> {1,2,3,4,5,6,7,8,9};
List <int> studentsIdList = new List<int> {1,3,5,7,9};

var q = 
        allStudents
        .GroupJoin(
                   studentsIdList, 
                   m => allStudents,
                   n => studentsIdList, 
                   (m, n) => new  {allS = m, excS = n.DefaultIfEmpty(0)})
        .Where(x => x.excS.SingleOrDefault () == 0)
        .Select (x => x.allS);

q.Dump();

I get a result set of 1,2,3,4,5,6,7,8,9

AND LINQPad does not show the lambda conversion.

Two questions:

  • What is wrong with my lambda query?
  • How do I get LINQPad to show the lambda translation?

UPDATE

Using the answer below I was able to correct my attempt

List<int> allStudents = new List<int> {1,2,3,4,5,6,7,8,9};
List <int> studentsIdList = new List<int> {1,3,5,7,9};

var q = allStudents
    .GroupJoin(studentsIdList, 
        a => a, b => b, 
        (a, b) => new { Id = a, Present = b.DefaultIfEmpty() })
    .Where(x => x.Present.Single() == 0)
    .Select(x => x.Id);

q.Dump();

Thanks very much.

Was it helpful?

Solution 2

This is how you write the join:

var q = allStudents
    .GroupJoin(studentsIdList, a => a, b => b, (a, b) => new { Id = a, Present = b })
    .Where(join => !join.Present.Any())
    .Select(join => join.Id);

Of course, for this very case, using Except would be much simpler.

Can't help with the Linqpad question as I don't use it myself.

OTHER TIPS

The answer to your second question, is to call .AsQueryable() on your source collection. This allows LINQPad to show C#'s translation into lambda syntax:

List<int> allStudents = new List<int> {1,2,3,4,5,6,7,8,9};
List <int> studentsIdList = new List<int> {1,3,5,7,9};
var q = from c in allStudents.AsQueryable()
        join p in studentsIdList on c equals p into ps 
        from p in ps.DefaultIfEmpty() 
        where p == 0
        select new { Student = c}; 

q.Dump();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top