首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >dotnet 10 LINQ LeftJoin & RightJoin

dotnet 10 LINQ LeftJoin & RightJoin

作者头像
郑子铭
发布2025-04-18 14:45:00
发布2025-04-18 14:45:00
14100
代码可运行
举报
运行总次数:0
代码可运行

dotnet 10 LINQ LeftJoin & RightJoin

Intro

.NET 10 Preview 1 为 LINQ 支持了 LeftJoinRightJoin,此前我们只支持 Join,需要自己实现,在 .NET 10 中将内置 LeftJoin/RightJoin 并且 EF 也将为之提供支持

New API

新增 API 如下:

代码语言:javascript
代码运行次数:0
运行
复制
namespace System.Linq;

publicstaticclassEnumerable
{
    publicstatic 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);

    publicstatic 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,
        IEqualityComparer<TKey>? comparer);

    publicstatic IEnumerable<TResult> RightJoin<TOuter, TInner, TKey, TResult>(
        this IEnumerable<TOuter> outer,  
        IEnumerable<TInner> inner,
        Func<TOuter, TKey> outerKeySelector,
        Func<TInner, TKey> innerKeySelector,
        Func<TOuter?, TInner, TResult> resultSelector);

    publicstatic IEnumerable<TResult> RightJoin<TOuter, TInner, TKey, TResult>(
        this IEnumerable<TOuter> outer,  
        IEnumerable<TInner> inner,
        Func<TOuter, TKey> outerKeySelector,
        Func<TInner, TKey> innerKeySelector,
        Func<TOuter?, TInner, TResult> resultSelector,
        IEqualityComparer<TKey>? comparer);
}

publicstaticclassQueryable
{
    publicstatic IQueryable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>(
        this IQueryable<TOuter> outer,
        IEnumerable<TInner> inner,
        Expression<Func<TOuter, TKey>> outerKeySelector,
        Expression<Func<TInner, TKey>> innerKeySelector,
        Expression<Func<TOuter, TInner?, TResult>> resultSelector);

    publicstatic IQueryable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>(
        this IQueryable<TOuter> outer,
        IEnumerable<TInner> inner,
        Expression<Func<TOuter, TKey>> outerKeySelector,
        Expression<Func<TInner, TKey>> innerKeySelector,
        Expression<Func<TOuter, TInner?, TResult>> resultSelector,
        IEqualityComparer<TKey>? comparer);
    
    publicstatic IQueryable<TResult> RightJoin<TOuter, TInner, TKey, TResult>(
        this IQueryable<TOuter> outer,
        IEnumerable<TInner> inner,
        Expression<Func<TOuter, TKey>> outerKeySelector,
        Expression<Func<TInner, TKey>> innerKeySelector,
        Expression<Func<TOuter?, TInner, TResult>> resultSelector);

    publicstatic IQueryable<TResult> RightJoin<TOuter, TInner, TKey, TResult>(
        this IQueryable<TOuter> outer,
        IEnumerable<TInner> inner,
        Expression<Func<TOuter, TKey>> outerKeySelector,
        Expression<Func<TInner, TKey>> innerKeySelector,
        Expression<Func<TOuter?, TInner, TResult>> resultSelector,
        IEqualityComparer<TKey>? comparer);
}

Sample

使用起来和 Join 类似,只是 LeftJoin/RightJoin 的时候可能会 map 不到数据导致有数据可能会 null,使用起来也是非常的简单,下面是一个简单的使用示例:

代码语言:javascript
代码运行次数:0
运行
复制
var jobs = new[]
{
    new
    {
        Id = 1,
        Name = "test"
    }
};
var employeeList = new[]
{
    new
    {
        Id = 1,
        JobId = 1,
        Name = "Alice"
    },
    new
    {
        Id = 2,
        JobId = 2,
        Name = "Jane"
    }
};
var result = employeeList.LeftJoin(jobs, e => e.JobId, j => j.Id, (e, j) => new
{
    e.Id,
    e.Name,
    e.JobId,
    JobName = j?.Name ?? "Unnamed"
});
foreach (var item in result)
{
    Console.WriteLine(JsonSerializer.Serialize(item));
}

这里两个员工对应两个 job 但是 job collection 里只有一个 job,会导致 left join 的时候,job 可能会为 null,我们设置了 JobName 在 Job 为 null 时显示为 Unnamed,执行结果如下:

left-join output

类似地我们也可以使用 right join

代码语言:javascript
代码运行次数:0
运行
复制
foreach (var item in jobs.RightJoin(employeeList, j => j.Id, e => e.JobId, (j, e) => new
        {
            e.Id,
            e.Name,
            e.JobId,
            JobName = j?.Name ?? "Unknown"
        }))
        {
            Console.WriteLine(JsonSerializer.Serialize(item));
        }

输出结果如下:

代码语言:javascript
代码运行次数:0
运行
复制
{"Id":1,"Name":"Alice","JobId":1,"JobName":"test"}
{"Id":2,"Name":"Jane","JobId":2,"JobName":"Unknown"}

More

如果要在已有的项目里使用,可以在自己的项目里实现一个扩展方法,实现代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
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)));
}

References

  • https://github.com/dotnet/runtime/issues/110292
  • https://github.com/dotnet/runtime/pull/110872
  • https://learn.microsoft.com/dotnet/api/system.linq.enumerable.join
  • https://github.com/WeihanLi/SamplesInPractice/blob/main/net10sample/Net10Samples/LinqSamples.cs
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • dotnet 10 LINQ LeftJoin & RightJoin
    • Intro
    • New API
    • Sample
    • More
    • References
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档