I wanted to create an extension method to enable left outer joins in linq/lambda IQueryables, and I have come up with the following, but I am still not sure it's completely correct.

public static IQueryable<TResult> LeftOuterJoin<TOuter, TInner, TKey, TResult>(
    this IQueryable<TOuter> outer,
    IQueryable<TInner> inner,
    Expression<Func<TOuter, TKey>> outerKeySelector,
    Expression<Func<TInner, TKey>> innerKeySelector,
    Func<TOuter, TInner, TResult> resultSelector)
    return outer.GroupJoin(
        (o, i) => new { outer = o, innerCollection = i })
        a => a.innerCollection.DefaultIfEmpty(),
        (a, i)=>resultSelector(a.outer,i));

I am especially concerned with the resultSelector being a Func, not an Expression, but I cant call an Expression in the lambda on the last line. I assume it gets cast automatically, but it's only an assumption.

Is this correct? How can I improve this? Can it be optimized more?

  • \$\begingroup\$ Have tested it? Does it generate a left outer join sql? \$\endgroup\$ – t3chb0t Jan 13 '17 at 13:33
  • \$\begingroup\$ I've tested it on AsQueriable collections, unfortunately haven't yet had the opportunity to test it on an actual database \$\endgroup\$ – Kravaros Jan 17 '17 at 12:16
  • 1
    \$\begingroup\$ If you didn't actually test it, how would you know if the improvements are improvements at all? \$\endgroup\$ – t3chb0t Jan 17 '17 at 12:25

Actually, it is way more complex than that, since Funcs<> cant't be translated to the database, so you'll have to "call" the expression. But since you can't call a expression, you'll have to change the expression into another that means what you need it to means.

Check out this question on StackOverflow. It has an good explanation on Linq inner workings and the accepted answer has a method that do the outer join. Be sure to read the second answer too, since it shows some issues that arise on more complex queries. And just as a warning, the method you are trying to write will easily gets 150 lines long (that's why I didn't copied it here)...

| improve this answer | |
  • \$\begingroup\$ Thank you for your answer, this is exactly what i was worried about. I will do some more reading on your link. \$\endgroup\$ – Kravaros Jan 17 '17 at 12:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.