I am trying to implement an outer join on this kind of query for the p.Person
table.
How would I do this?
This example is taken from http://ashishware.c
If anyone comes across this question and wants an extension method to accomplish this, I created one using the same approach as the other answers. It has the same signature as the regular join extension method.
public static IEnumerable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector)
{
return outer
.GroupJoin(inner, outerKeySelector, innerKeySelector, (outerObj, inners) =>
new
{
outerObj,
inners= inners.DefaultIfEmpty()
})
.SelectMany(a => a.inners.Select(innerObj => resultSelector(a.outerObj, innerObj)));
}
For Left outer Join try Following query. This is tested
var leftJoin = Table1
.GroupJoin(
inner: Table2,
outerKeySelector: t1 => t1.Col1,
innerKeySelector: t2 => t2.Col2,
resultSelector: ( t1, t2Rows ) => new { t1, t2Rows.DefaultIfEmpty() }
)
.SelectMany( z =>
z.t2Rows.Select( t2 =>
new { t1 = z.t1, t2 = t2 }
)
);
Normally left joins in LINQ are modelled with group joins, sometimes in conjunction with DefaultIfEmpty
and SelectMany
:
var leftJoin = p.Person.Where(n => n.FirstName.Contains("a"))
.GroupJoin(p.PersonInfo,
n => n.PersonId,
m => m.PersonId,
(n, ms) => new { n, ms = ms.DefaultIfEmpty() })
.SelectMany(z => z.ms.Select(m => new { n = z.n, m }));
That will give a sequence of pairs (n, m) where n
is the entry from p.Person
and m
is the entry from p.PersonInfo
, but m
will be null if there are no matches.
(It's completely untested, btw - but should give you the idea anyway :)