30

Possible Duplicate:
How do you perform a left outer join using linq extension methods

I can't find a left outer join example of Linq lambda (with extension methods), at least, not a clear one.

Let's say I have the following table:

Parent
{
    PID     // PK
}

Child
{
    CID     // PK
    PID     // FK
    Text
}

I want to join Parent with Child, and for every child missing, I want the default value for Text to be "[[Empty]]". How can I do this with linq lambda syntax?

I currently have the following:

var source = lParent.GroupJoin(
    lChild,
    p => p.PID,
    c => c.PID,
    (p, g) =>
        new // ParentChildJoined
        {
            PID = p.PID;
            // How do I add child values here?
        });
Community
  • 1
  • 1
NomenNescio
  • 2,899
  • 8
  • 44
  • 82

2 Answers2

78

You're close. The following will select PID, CID and Text for each child, and PID, CID = -1 and Text = "[[Empty]]" for each parent with no children:

var source = lParent.GroupJoin(
    lChild,
    p => p.PID,
    c => c.PID,
    (p, g) => g
        .Select(c => new { PID = p.PID, CID = c.CID, Text = c.Text })
        .DefaultIfEmpty(new { PID = p.PID, CID = -1, Text = "[[Empty]]" }))
    .SelectMany(g => g);
Rawling
  • 49,248
  • 7
  • 89
  • 127
7
from p in Parent
join c in Child on p.PID equals c.PID into g
from c in g.DefaultIfEmpty()
select new 
{
   p.PID,
   CID = c != null ? (int?)c.CID : null, // Could be null
   Text = c != null ? c.Text : "[[Empty]]"
}

With lambda:

class ChildResult
{
   public int PID { get; set; }
   public int? CID { get; set; }
   public string Text { get; set; }
}

lParent.SelectMany(p => p.Childs.Any() ?
  p.Childs.Select(c => new ChildResult() { PID = c.PID, CID = c.CID, Text = c.Text }) :
  new [] { new ChildResult() { PID = p.PID, CID = null, Text = "[[Empty]]" } } );
ChrisF
  • 134,786
  • 31
  • 255
  • 325
Amiram Korach
  • 13,056
  • 3
  • 28
  • 30