C# 如何在LINQ中使用Join - 连接两个数据源

LINQ 的 Join 实现内连接,需传入内集合、外键选择器、内键选择器和结果选择器四个参数,仅支持等值匹配且键类型必须一致,性能优于嵌套循环。

在 C# 的 LINQ 中,Join 用于对两个数据源(如集合)基于键进行内连接(inner join),类似 SQL 的 INNER JOIN。它不支持左连接或全连接,但可通过 GroupJoin 配合 DefaultIfEmpty() 实现。

基本语法:Join 的四个参

Join 方法需要传入四个关键参数:

  • 内集合(inner):被连接的第二个数据源(如 orders
  • 外键选择器(outerKeySelector):从外集合中提取用于匹配的键(如 customer => customer.Id
  • 内键选择器(innerKeySelector):从内集合中提取用于匹配的键(如 order => order.CustomerId
  • 结果选择器(resultSelector):定义连接后如何组合两条记录(如 (c, o) => new { c.Name, o.OrderDate }

简单示例:连接客户和订单

假设有两个列表:

var customers = new List
{
    new Customer { Id = 1, Name = "张三" },
    new Customer { Id = 2, Name = "李四" }
};

var orders = new List { new Order { Id = 101, CustomerId = 1, OrderDate = DateTime.Today }, new Order { Id = 102, CustomerId = 1, OrderDate = DateTime.Today.AddDays(-1) } };

执行连接:

var result = customers.Join(
    orders,
    c => c.Id,           // 外键:客户ID
    o => o.CustomerId,    // 内键:订单中的客户ID
    (c, o) => new { c.Name, o.OrderDate }  // 结果:匿名对象
);

输出会包含两条记录(因为只有客户 1 有订单),客户 2 不会出现——这是内连接特性。

使用 Join 注意的关键点

键类型必须一致:外键和内键返回的类型需相同或可隐式转换(如 int 与 long 不行,需显式转换)。

只支持等值连接:LINQ 的 Join 仅支持 == 匹配,不支持 >Contains 等复杂条件;如需非等值逻辑,改用 Where + from ... from ... where 查询表达式。

性能较优:底层会将内集合构建成哈希表,时间复杂度接近 O(n+m),比嵌套循环高效。

替代写法:查询表达式语法(更直观)

上面的连接也可写成:

var result = from c in customers
             join o in orders on c.Id equals o.CustomerId
             select new { c.Name, o.OrderDate };

语义完全等价,on ... equals ... 是固定语法,不能写成 == 或其他操作符。

基本上就这些。掌握 Join 的四个参数含义和等值匹配限制,就能稳妥完成大多数集合关联需求。