2
\$\begingroup\$

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(
 inner,
 outerKeySelector,
 innerKeySelector,
 (o, i) => new { outer = o, innerCollection = i })
 .SelectMany(
 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?

Malachi
29k11 gold badges86 silver badges188 bronze badges
asked Jan 13, 2017 at 12:41
\$\endgroup\$
3
  • \$\begingroup\$ Have tested it? Does it generate a left outer join sql? \$\endgroup\$ Commented Jan 13, 2017 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\$ Commented Jan 17, 2017 at 12:16
  • 1
    \$\begingroup\$ If you didn't actually test it, how would you know if the improvements are improvements at all? \$\endgroup\$ Commented Jan 17, 2017 at 12:25

1 Answer 1

3
\$\begingroup\$

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)...

answered Jan 17, 2017 at 5:52
\$\endgroup\$
1
  • \$\begingroup\$ Thank you for your answer, this is exactly what i was worried about. I will do some more reading on your link. \$\endgroup\$ Commented Jan 17, 2017 at 12:17

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.