0

From this thread I found how to do left join in LINQ. I created an extension method as given in the answer by bcwhims. I found out using SQL profiler that using that extension method it actually executes two separate queries (select all) of the constituent tables, and then does the left join in memory. However, when I execute the same query in place, that is, without using an extension method, it emits left outer join SQL as expected. For reference this is the extension method I am using:

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)));
}

So it seems there is something wrong with this extension method. Note that the result it returns is correct, my concern is about it executing two "select all" queries. Please let me know what modifications I need to make to this extension method so that it emits correct SQL for left join. I have tried changing the IEnumerables to IQueryables, but still it does two "select all" queries. This is the version that I used using IQueryable:

public static IQueryable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>(
    this IQueryable<TOuter> outer,
    IQueryable<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)))
    .AsQueryable();
}
Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
  • 1
    Is there a particular reason you are using `IEnumerable` rather than `IQueryable`? Does it act differently if you change `IEnumerable` to `IQueryable`? Can you edit your question to show that attempt (leave your old code there)? – mjwills Jul 15 '19 at 10:22
  • Does using `Expression` rather than `Func` help? – mjwills Jul 15 '19 at 10:27
  • 2
    The selectors need to be expressions rather than func's – Magnus Jul 15 '19 at 10:29
  • The [LinqKit answer](https://stackoverflow.com/a/39890771/468973) in the dupe question seems to be to most painless way. – Magnus Jul 15 '19 at 10:39

0 Answers0