如何在JOIN扩展方法中实现左连接

Sha*_*pta 29 c# linq extension-methods

我试图在p.Person表的这种查询上实现外连接.我该怎么做?

此示例来自http://ashishware.com/DSLinqExample.shtml

var onlyinfo = p.Person
    .Where(n => n.FirstName.Contains('a'))
    .Join(p.PersonInfo,
        n => n.PersonId,
        m => m.PersonId,
        (n, m) => m)
    .ToArray<Persons.PersonInfoRow>();
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 53

通常,LINQ中的左连接使用组连接建模,有时与DefaultIfEmptySelectMany:

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 }));
Run Code Online (Sandbox Code Playgroud)

这将给出一系列对(n,m),其中n是条目,p.Person并且m是条目p.PersonInfo,但m如果没有匹配则为null.

(它完全未经测试,顺便说一句 - 但无论如何应该给你这个想法:)


小智 14

对于Left outer Join尝试以下查询.这是经过测试的

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 }
                    )
                );
Run Code Online (Sandbox Code Playgroud)


bcw*_*ims 8

如果有人遇到这个问题,并想要一个扩展方法来实现这一点,我使用与其他答案相同的方法创建了一个.它具有与常规连接扩展方法相同的签名.

    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))); 
    }
Run Code Online (Sandbox Code Playgroud)

  • 在我的测试中,这不会发出 SQL 左连接查询,而是执行两个彼此独立的单独查询,然后在内存中执行左连接。但是,当我就地执行相同的操作(即不使用扩展方法)时,它会按预期发出“左外连接”。 (2认同)