首页 > 解决方案 > 左连接扩展方法(使用 DefaultIfEmpty)不发出 SQL 左连接

问题描述

这个线程我发现了如何在 LINQ 中进行左连接。我创建了bcwhims的答案中给出的扩展方法。我发现使用 SQL 分析器使用该扩展方法实际上执行了两个单独的查询(全选)组成表,然后在内存中进行左连接。但是,当我就地执行相同的查询时,即不使用扩展方法时,它会left outer join按预期发出 SQL。作为参考,这是我正在使用的扩展方法:

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

因此,这种扩展方法似乎有问题。请注意,它返回的结果是正确的,我担心它会执行两个“全选”查询。请让我知道我需要对此扩展方法进行哪些修改,以便它为左连接发出正确的 SQL。我尝试将 IEnumerables 更改为 IQueryables,但它仍然执行两个“全选”查询。这是我使用 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();
}

标签: c#linqleft-join

解决方案


推荐阅读