)
码农刚子 · 六年制造业 ERP / .NET 实战 · 只写生产环境踩过的坑摘要2026 年 11 月 10 日.NET 8 与 .NET 9 同时终止官方支持。从 .NET 8 直接跨两代升 .NET 10breaking change 远多于 8→9。本文总结升级前 4 项必查、生产中 5 个真实踩坑、以及 6 步安全落地清单照着走能避开绝大多数线上事故。2026 年 11 月 10 日是条躲不过的死线。这一天之后.NET 8 和 .NET 9 都终止官方支持不再有安全补丁。线上跑着的 ERP 接口、后台任务、内部工具等于在公网里裸奔——漏洞不再有人修合规审计一查一个准。但一线实践里最常见的情况是既然都要升今晚就改个版本号发上去。结果升级当天线上就崩的概率反而比拖着不升更高。升级从来不是把net8.0改成net10.0那么一行的事。下面这几道坑是我在制造业 ERP 系统上真刀真枪升过、崩过、才总结出来的。一、先看清你跳过的不是一个版本把版本支持周期摆出来就明白为什么这次不能无脑升版本类型支持终止.NET 8LTS2026-11-10.NET 9STS2026-11-10.NET 10LTS2028-11-10从 .NET 8 直接跳 .NET 10中间隔了一个 .NET 9。这意味着你跨了两个大版本累积的 breaking change 比 8→9 那一跳要多得多。微软的官方迁移文档也是按 8→9、9→10 分别给的没有一步到位的捷径。换句话说.NET 10 是 LTS能稳到 2028 年方向没错但过程必须按跨两代的复杂度来对待。二、升级前必做的 4 项检查自检表动代码之前先花半小时把下面四件事过一遍能挡掉八成的升级事故。① 第三方依赖有没有 net10.0 / netstandard2.1 兼容包这是最容易翻车的地方。项目里引用的组件往往不是微软官方那几个而是社区或商业库。重点盯这三类UI 组件库如 Radzen.Blazor 这类轻量 ORM如 Dapper 及其扩展旧版 SDK、内部打包的私有 NuGet⚠ 经验表明不少库在 .NET 大版本发布后几周内才跟上 net10.0 包。升之前先去 NuGet 上看一眼目标版本支持的TargetFramework。② 项目文件里的 TargetFramework 及相关开关不只是改 TFM这几个现有设置要心里有数PropertyGroup TargetFrameworknet10.0/TargetFramework LangVersionlatest/LangVersion ImplicitUsingsenable/ImplicitUsings Nullableenable/Nullable /PropertyGroupLangVersion、ImplicitUsings、Nullable的当前值决定了你老代码升上去后会不会看起来一样、实际已变。③ 扫描已 Obsolete / 已移除的 API最典型的是BinaryFormatter——它在 .NET 9 起被彻底移除升级后直接编译不过。代码里但凡有BinaryFormatter.Serialize / Deserialize要提前换成System.Text.Json或MemoryPack之类。可以用 Roslyn 分析器或dotnet list package --deprecated辅助扫描别靠肉眼。④ 全球化 / 编码的默认行为容器化部署docker 镜像里.NET 默认开启Invariant Globalization也就是全球化不变模式。结果是中文排序、本地化资源、ToString()的某些格式可能和你开发机上的表现悄悄不一样。如果系统有中文字段排序、按区域设置格式化日期/数字的逻辑升级前务必在容器里实测一遍。三、生产环境真实踩过的坑下面几个坑都是本地能跑、一上生产就炸的典型。坑1依赖库主版本没出 net10 包build 直接红最尴尬的情况核心业务依赖的某个组件官方还没发布兼容 .NET 10 的版本。CI 一拉包就报错编译根本过不去。两种兜底要么等官方更新要么在依赖项目里临时加net10.0到TargetFrameworks做多目标编译前提是它的代码本身兼容。但多 target 只是临时止血不是长久方案上线前要记到技术债清单里。坑2ImplicitUsings 开启后老代码重复 usingImplicitUsings是 .NET 6 起就有的隐式命名空间机制。升到新版本后如果旧代码里保留了手写using System;、using System.Linq;而全局又自动引入了同名命名空间编译器会报CS0105命名空间重复。更隐蔽的是新增的隐式命名空间可能和你自建的类或扩展方法重名编译期不报错运行期行为却变了。建议升级时统一清理冗余 using并打开TreatWarningsAsErrors让隐患暴露。坑3System.Text.Json 默认行为变化前端解析崩多数情况下跨大版本后System.Text.Json的默认行为命名策略、空值处理、保留引用、数字处理等会有微调。后果很直接接口返回的字段大小写或结构变了前端按老字段名解析拿到undefined页面白屏。✓ 落地经验别依赖默认序列化选项显式声明最稳var options new JsonSerializerOptions { PropertyNamingPolicy JsonNamingPolicy.CamelCase, DefaultIgnoreCondition JsonIgnoreCondition.WhenWritingNull };升级后把前后端契约过一遍契约测试比事后救火便宜得多。坑4开了 trimming / AOT 的项目反射失效⚠ 注意这个坑只影响显式开了PublishAottrue/PublishAot或 trimming 的项目普通项目不受影响。一旦启用 AOT反射、运行时按字符串Type.GetType、动态 JSON 映射到object、依赖运行期类型发现的库都会在发布后失效——本地dotnet run正常一dotnet publish就炸。这类项目升级时要把所有靠反射运行时探活的代码改成显式[JsonSerializable]源生成或提前注册。坑5补充EF Core 8→10 的可空引用与查询翻译启用Nullable后EF Core 对查询翻译更严格了。部分在 8 上默默走客户端评估的 LINQ到 10 可能直接抛异常可空引用警告若被当作错误TreatWarningsAsErrors编译也会卡住。建议升级后跑一遍完整查询回归别只信单测绿。四、安全落地 6 步清单把上面这些消化掉按这套流程走基本能平稳过渡备份 开分支数据库全量备份代码拉upgrade/net10长分支绝不主干直接改。改 TFMnet8.0→net10.0顺手核对LangVersion/ImplicitUsings/Nullable。升 NuGet把所有依赖升到支持 net10.0 的版本删掉被移除的包如老 BinaryFormatter 相关。扫弃用与警告跑构建把Obsolete警告、CS 警告当错误处理逐个清零。本地 build / test 全绿单测、集成测、契约测全过再谈发布。灰度发布观察先小流量灰度盯错误率、延迟、内存稳了再全量。✓ 关键原则先小流量灰度再全量。制造业系统的高峰期如月末结账、排产一旦崩影响的是真金白银的产线没有回滚预案别碰。五、写在最后升级 .NET 10 不是赶时髦是 2026-11-10 死线逼出来的必答题。坑都在这儿了照着清单走你能避开绝大多数线上事故。阅读原文从 .NET 8 升 .NET 10 实战生产环境这几个坑不避开就崩 - 码录集本文为通用 .NET 升级方法论分享不涉及任何企业专有业务细节。