linqmethod 实现 leftjoin

intro

有时候我们想实现 leftjoin 但是 linq 提供的 join 相当于是 inner join,于是就打算实现一个 leftjoin 的扩展。
如果要使用到左连接,你需要使用 defaultifempty 来在没有join到数据的时候返回默认的集合

solution

源代码:https://github.com/weihanli/weihanli.common/blob/dev/src/weihanli.common/extensions/enumerableextension.cs#l149

/// <summary>
/// leftjoin extension
/// </summary>
/// <typeparam name="touter">outer</typeparam>
/// <typeparam name="tinner">inner</typeparam>
/// <typeparam name="tkey">tkey</typeparam>
/// <typeparam name="tresult">tresult</typeparam>
/// <param name="outer">outer collection</param>
/// <param name="inner">inner collection</param>
/// <param name="outerkeyselector">outerkeyselector</param>
/// <param name="innerkeyselector">innerkeyselector</param>
/// <param name="resultselector">resultselector</param>
/// <returns></returns>
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)));
}

use

使用起来和 join 差不多,下面来展示一个示例:

var posts = new[] { new { postid = 1, posttitle = "12333", }, new { postid = 2, posttitle = "12333", }, };
var posttags = new[] { new { postid = 1, tag = "hhh" } };

var result = posts.leftjoin(posttags, p => p.postid, pt => pt.postid, (p, pt) => new { p.postid, p.posttitle, pt?.tag }).toarray();
console.writeline(result.tojson());

输出:

[{"postid":1,"posttitle":"12333","tag":"hhh"},{"postid":2,"posttitle":"12333"}]

memo

这是使用 linqmethod 实现 leftjoin,如果要使用 linq 查询语法实现左连接请参考

reference

  • https://github.com/weihanli/weihanli.common