C# Join 实战:左连接写法、字符串拼接与 EF Core 性能调优

引言

大家好,我是刚子。

实际业务中,左连接(Left Join)远比内连接常见;而 string.Join 和 EF Core 中的 Join 又是两个极易被滥用的高频场景。本文为你提供这三者的实战解决方案。

一、LINQ to Objects 中的 Left Join 写法

Join 本身只支持内连接,要实现左连接必须使用 GroupJoin 配合 SelectManyDefaultIfEmpty

标准模版

复制代码
var leftJoin = customers
    .GroupJoin(orders,
        c => c.Id,
        o => o.CustomerId,
        (c, orderGroup) => new { Customer = c, Orders = orderGroup })
    .SelectMany(
        x => x.Orders.DefaultIfEmpty(),
        (x, order) => new { x.Customer, Order = order });

输出说明 :若客户没有订单,Order 字段为 null。可在 select 中进一步处理。

二、string.Join 性能优化 ------ 什么时候用它,什么时候用 StringBuilder

string.Join 专为已知列表/数组的快速拼接设计,内部使用 FastAllocateString 和指针操作,性能极佳。但在动态循环中反复追加,则必须使用 StringBuilder

场景对比

场景 推荐方法 原因
string[] names = { "A", "B" } string.Join 内部已预先算好总长度,一次分配内存,比循环 += 快 10~100 倍
foreach 动态添加未知数量的字符串 StringBuilder 不会频繁创建新字符串对象,避免内存碎片

错误示例(性能极差):

复制代码
string result = "";
foreach(var s in list) result = result + s + ",";  // 每次+都新建字符串

正确做法

复制代码
var sb = new StringBuilder();
foreach(var s in list) sb.Append(s).Append(',');
string result = sb.ToString().TrimEnd(',');

三、Entity Framework Core 中的 Join 性能优化

EF Core 中滥用 Join 可能导致生成低效的 SQL(例如 N+1 子查询或不必要的笛卡尔积)。

问题一:默认 Join 生成 INNER JOIN 但会失去导航属性的预加载能力

优化 :优先使用导航属性 + Include,而不是手动 Join

复制代码
// 推荐
var orders = context.Orders.Include(o => o.Customer).ToList();

// 不推荐(虽然功能相同,但无法利用 Include 缓存)
var query = context.Orders.Join(context.Customers, ...);

问题二:多表 Join 导致笛卡尔积膨胀

当关联三张以上表且均为一对多时,EF 默认会生成一个包含所有表的单条 SQL,结果集行数 = 表1行 × 表2匹配数 × 表3匹配数,数据量爆炸。

解决方案 :使用 AsSplitQuery() 强制 EF 生成多条 SQL,在客户端内存中关联。

复制代码
var query = context.Orders
    .Join(context.Customers, ...)
    .Join(context.Shippers, ...)
    .AsSplitQuery()   // 关键
    .ToList();

注意AsSplitQuery 会增加数据库往返次数,但能大幅减少数据传输量。适用于连接结果行数远大于原始表总行数的场景。

总结

  • LEFT JOIN 的标准写法 = GroupJoin + SelectMany + DefaultIfEmpty
  • 已知集合用 string.Join,动态循环用 StringBuilder
  • EF Core 中能用导航属性就别手动 Join,多表关联时评估是否使用 AsSplitQuery()

我是刚子,一个还在写 .NET 的程序员。咱们下回见!

原文链接:C# Join 实战:左连接写法、字符串拼接与 EF Core 性能调优 - 码农刚子的开发笔记

相关推荐
傻啦嘿哟1 小时前
某招聘平台爬虫:爬取招聘岗位数据,分析各城市薪资水平
开发语言·爬虫·python
2501_933670791 小时前
2026秋招量化分析岗技能栈:Python、SQL、统计建模、回测项目怎么准备
开发语言·python·sql
李少兄2 小时前
JavaScript 数据类型完全指南
开发语言·javascript·ecmascript
Seoyoneh2 小时前
Agentic Workflow编排架构:云客服从“被动响应”迈向“主动执行”的技术实现
java·开发语言·架构
Tangyuewei3 小时前
Java 写 Agent:模型只是组件
java·开发语言
小玮看世界3 小时前
[Python]从合并区间到传感器融合区:合并区间在传感器区域融合的实际落地
开发语言·python
繁星蓝雨4 小时前
C++的设计与演进大纲(如何从C语言一步步成长为C++)
c语言·开发语言·c++·c++历史·c++演进
Evand J4 小时前
【MATLAB例程,图像降噪滤波9】自适应维纳滑动窗口滤波(Wiener)图像降噪、方法对比,有中文注释
开发语言·图像处理·计算机视觉·matlab·滑动窗口·滤波·降噪
杜大哥4 小时前
python程序:如何查看电脑【电池电量的剩余百分比】 和 【是否插入连接着充电器】?
开发语言·python
wuyk5554 小时前
Python网络爬虫入门到实战 第01章:爬虫到底是什么?原理、流程、合法性、风险全解析(零基础必看)
开发语言·爬虫·python