代码之家  ›  专栏  ›  技术社区  ›  Shantanu Gupta

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

  •  27
  • Shantanu Gupta  · 技术社区  · 14 年前

    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>();
    
    3 回复  |  直到 11 年前
        1
  •  59
  •   Michał Turczyn    7 年前

    通常,LINQ中的左连接是用组连接建模的,有时与 DefaultIfEmpty SelectMany :

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

    n p.Person m 是从 p.PersonInfo ,但是

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

        2
  •  16
  •   Dai    8 年前

    对于左外联接,请尝试以下查询。这是经过测试的

    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 }
                        )
                    );
    
        3
  •  11
  •   bcwhims    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))); 
        }