mcpField
M
migrate-dotnet9-to-dotnet10

migrate-dotnet9-to-dotnet10

github.com/dotnet开发5.8k3.6k 次安装1 天前更新
代码仓库

关于 migrate-dotnet9-to-dotnet10

帮助将 .NET 9 项目或解决方案迁移到 .NET 10,并系统处理破坏性变更。涵盖编译、运行时、框架及部署配置,并通过构建和测试验证结果。

主要功能

  1. 01评估项目与 SDK 状态
  2. 02更新目标框架和包
  3. 03处理编译层面的变更
  4. 04检查运行时行为变化
  5. 05更新 CI/CD 和部署文件
  6. 06验证构建与测试

适用场景

  1. 01将 net9.0 项目升级到 net10.0
  2. 02修复安装 .NET 10 SDK 后的错误
  3. 03适配 ASP.NET Core 或 EF Core 代码
  4. 04更新容器或 CI/CD 配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dotnet/skills --skill migrate-dotnet9-to-dotnet10

安装后在 Claude Code 中输入/migrate-dotnet9-to-dotnet10确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
aspnet-core-dotnet9to10.md
containers-interop-dotnet9to10.md
core-libraries-dotnet9to10.md
cryptography-dotnet9to10.md
csharp-compiler-dotnet9to10.md
efcore-dotnet9to10.md
extensions-hosting-dotnet9to10.md
sdk-msbuild-dotnet9to10.md
serialization-networking-dotnet9to10.md
winforms-wpf-dotnet9to10.md

详细介绍

.NET 9 → .NET 10 迁移

将 .NET 9 项目或解决方案迁移到 .NET 10,并系统地解决所有重大更改。最终项目将以 net10.0 为目标框架,能够顺利构建、通过测试,并处理 .NET 10 版本引入的所有行为更改、源代码不兼容更改和二进制不兼容更改。

适用场景

  • 将 TargetFramework 从 net9.0 升级到 net10.0
  • 更新 .NET 10 SDK 后解决构建错误或新警告
  • 适配 .NET 10 运行时、ASP.NET Core 10 或 EF Core 10 的行为更改
  • 更新 .NET 10 的 CI/CD 流水线、Dockerfile 或部署脚本
  • 从社区提供的 System.Linq.Async 包迁移到内置的 System.Linq.AsyncEnumerable

不适用场景

  • 项目已以 net10.0 为目标框架且构建顺利 — 迁移已完成
  • 从 .NET 8 或更早版本升级 — 请先使用 migrate-dotnet8-to-dotnet9 技能升级到 net9.0,然后再使用此技能完成从 net9.0 到 net10.0 的迁移
  • 从 .NET Framework 迁移 — 这是另一项规模更大的工作
  • 从零开始创建并以 .NET 10 为目标框架的项目(无需迁移)

输入

输入必需说明
项目或解决方案路径是要迁移的 .csproj、.sln 或 .slnx 入口点
构建命令否构建方式(例如 dotnet build、仓库构建脚本)。未提供时自动检测
测试命令否运行测试的方式(例如 dotnet test)。未提供时自动检测
项目类型提示否项目是否使用 ASP.NET Core、EF Core、WinForms、WPF、容器等。未提供时根据 PackageReferences 和 SDK 属性自动检测

工作流

直接依据已加载的参考文档作答。 请勿搜索文件系统或抓取网页来查找重大更改信息——参考文档包含权威详情。重点识别适用的重大更改并给出具体修复方案。**例外:**如果怀疑项目依赖项可能存在安全漏洞(CVE),请检查已发布的安全公告——参考文档可能未涵盖发布后的 CVE。

**提交策略:**在每个逻辑阶段完成后提交——更新 TFM 后(步骤 2)、解决构建错误后(步骤 3)、处理行为更改后(步骤 4)以及更新基础设施后(步骤 5)。这样每次提交内容集中,便于审查。

步骤 1:评估项目
  1. 确定项目的构建和测试方式。查找构建脚本、.sln/.slnx 文件或单独的 .csproj 文件。
  2. 运行 dotnet --version,确认已安装 .NET 10 SDK。若未安装,请停止并告知用户。
  3. 检查以下内容,确定项目使用的技术领域:
    • SDK 属性:Microsoft.NET.Sdk.Web → ASP.NET Core;使用 <UseWPF> 或 <UseWindowsForms> 的 Microsoft.NET.Sdk.WindowsDesktop → WPF/WinForms
    • PackageReferences:Microsoft.EntityFrameworkCore.* → EF Core;Microsoft.Data.Sqlite → Sqlite;Microsoft.Extensions.Hosting → Generic Host / BackgroundService
    • 存在 Dockerfile → 适用容器更改
    • 使用 P/Invoke 或本机互操作 → 适用互操作更改
    • 引用 System.Linq.Async 包 → 需要迁移到 AsyncEnumerable
    • 使用带多态功能的 System.Text.Json → 适用序列化更改
  4. 记录相关的参考文档(参见步骤 3 的参考文档加载表)。
  5. 在当前 net9.0 目标框架上执行一次干净构建(运行 dotnet build --no-incremental 或删除 bin/obj),建立干净的基线。记录所有已有警告。
步骤 2:更新目标框架
  1. 在每个 .csproj 文件中(或集中配置时,在 Directory.Build.props 中),将:

    <TargetFramework>net9.0</TargetFramework>
    

    改为:

    <TargetFramework>net10.0</TargetFramework>
    

    对于多目标项目,将 net10.0 添加到 <TargetFrameworks>,或替换 net9.0。

  2. 将所有 Microsoft.Extensions.*、Microsoft.AspNetCore.*、Microsoft.EntityFrameworkCore.* 及其他 Microsoft 包引用更新到 10.0.x 版本。如果使用中央包管理(Directory.Packages.props),请在那里更新版本。

  3. 运行 dotnet restore。注意以下情况:

    • NU1510:NuGet 修剪了直接引用 — 该包现在可能已包含在共享框架中。如果是这样,请移除显式的 <PackageReference>。
    • 不带版本的 PackageReference 现在会引发错误 — 每个 <PackageReference> 都必须指定 Version(或使用 CPM)。
    • NuGet 对传递包进行审核(dotnet restore 现在会审核传递依赖项)— 检查所有新增的漏洞警告。
  4. 执行干净构建。收集所有错误和新增警告,并在步骤 3 中处理。

步骤 3:解决构建错误和源代码不兼容的更改

系统地处理编译错误和新增警告。根据项目类型加载相应的参考文档:

如果项目使用……加载参考文档
任何 .NET 10 项目references/csharp-compiler-dotnet9to10.md
任何 .NET 10 项目references/core-libraries-dotnet9to10.md
任何 .NET 10 项目references/sdk-msbuild-dotnet9to10.md
ASP.NET Corereferences/aspnet-core-dotnet9to10.md
Entity Framework Corereferences/efcore-dotnet9to10.md
加密 APIreferences/cryptography-dotnet9to10.md
Microsoft.Extensions.Hosting、BackgroundService、配置references/extensions-hosting-dotnet9to10.md
System.Text.Json、XmlSerializer、HttpClient、MailAddress、Urireferences/serialization-networking-dotnet9to10.md
Windows Forms 或 WPFreferences/winforms-wpf-dotnet9to10.md
Docker 容器、单文件应用、原生互操作references/containers-interop-dotnet9to10.md

需要检查的常见源代码不兼容更改:

  1. System.Linq.Async 冲突 — 移除 System.Linq.Async 包引用,或升级到 v7.0.0。如果该包是传递依赖,请添加 <ExcludeAssets>compile</ExcludeAssets>。在需要的地方,将 SelectAwait 调用改为 Select。

  2. 新增的弃用警告(SYSLIB0058–SYSLIB0062):

    • SYSLIB0058:将 SslStream.KeyExchangeAlgorithm/CipherAlgorithm/HashAlgorithm 替换为 NegotiatedCipherSuite — 如果旧属性用于拒绝弱 TLS 密码套件,请使用新 API 保留等效的验证逻辑
    • SYSLIB0059:将 SystemEvents.EventsThreadShutdown 替换为 AppDomain.ProcessExit
    • SYSLIB0060:将 Rfc2898DeriveBytes 构造函数替换为 Rfc2898DeriveBytes.Pbkdf2
    • SYSLIB0061:将采用 IComparer<TSource> 的 Queryable.MaxBy/MinBy 重载替换为采用 IComparer<TKey> 的重载
    • SYSLIB0062:替换 XsltSettings.EnableScript 的用法
  3. C# 14 属性访问器中的 field 关键字 — 标识符 field 现在是属性 get/set/init 访问器中的上下文关键字。名为 field 的局部变量会导致 CS9272(错误)。引用时未加 this. 的名为 field 的类成员会导致 CS9258(警告)。可通过重命名(例如 fieldValue)或使用 @field 转义来修复。请参阅 references/csharp-compiler-dotnet9to10.md。

  4. C# 14 extension 上下文关键字 — 不允许将类型、别名或类型参数命名为 extension。请重命名或使用 @extension 转义。

  5. 带 Span 参数的 C# 14 重载解析 — 数组上包含 .Contains() 的表达式树现在可能会绑定到 MemoryExtensions.Contains,而不是 Enumerable.Contains。数组上的 Enumerable.Reverse 可能会解析为就地修改的 Span 扩展方法。可通过转换为 IEnumerable<T>、使用 .AsEnumerable() 或显式静态调用来修复。完整详情请参阅 references/csharp-compiler-dotnet9to10.md。

  6. ASP.NET Core 弃用项(如适用):

    • WebHostBuilder、IWebHost、WebHost 已弃用 — 迁移到 Host.CreateDefaultBuilder 或 WebApplication.CreateBuilder
    • IActionContextAccessor / ActionContextAccessor 已弃用
    • WithOpenApi 扩展方法已弃用
    • IncludeOpenAPIAnalyzers 属性已弃用
    • IPNetwork 和 ForwardedHeadersOptions.KnownNetworks 已弃用
    • Razor 运行时编译已弃用
    • Microsoft.Extensions.ApiDescription.Client 包已弃用
    • Microsoft.OpenApi v2.x 的破坏性变更 — Microsoft.AspNetCore.OpenApi 10.0 引入的 Microsoft.OpenApi v2.x 重组了命名空间和模型。OpenApiString / OpenApiAny 类型已移除(改用 JsonNode),OpenApiSecurityScheme.Reference 已替换为 OpenApiSecuritySchemeReference,OpenAPI 模型对象上的集合可能为 null,且 OpenApiSchema.Nullable 已移除。迁移模式请参阅 references/aspnet-core-dotnet9to10.md。
  7. SDK 变更:

    • dotnet new sln 现在默认使用 SLNX 格式 — 如需旧格式,请使用 --format sln
    • 文件级指令中不允许使用双引号
    • .NET SDK 已移除 dnx.ps1
    • dotnet restore 不再支持 project.json
  8. EF Core 源代码变更(如适用)— 参阅 references/efcore-dotnet9to10.md,了解以下内容:

    • ExecuteUpdateAsync 现在接受常规 Lambda(必须重写表达式树构造代码)
    • IDiscriminatorPropertySetConvention 签名已变更
    • IRelationalCommandDiagnosticsLogger 方法新增了 logCommandText 参数
  9. WinForms/WPF 源代码变更(如适用):

    • 同时引用 WPF 和 WinForms 的应用程序必须消除 MenuItem 和 ContextMenu 类型的歧义
    • HtmlElement.InsertAdjacentElement 中的参数已重命名
    • WPF 不允许使用空的 ColumnDefinitions 和 RowDefinitions
  10. 加密源代码变更(如适用):

  • MLDsa 和 SlhDsa 成员的名称已从 SecretKey 改为 PrivateKey(例如,ExportMLDsaSecretKey → ExportMLDsaPrivateKey,SecretKeySizeInBytes → PrivateKeySizeInBytes)
  • Rfc2898DeriveBytes 构造函数已弃用(SYSLIB0060)— 替换为静态方法 Rfc2898DeriveBytes.Pbkdf2(password, salt, iterations, hashAlgorithm, outputLength)
  • CoseSigner.Key 现在可以为 null — 使用前请检查是否为 null
  • X509Certificate.GetKeyAlgorithmParameters() 和 PublicKey.EncodedParameters 可能返回 null
  • 环境变量已从 CLR_OPENSSL_VERSION_OVERRIDE 重命名为 DOTNET_OPENSSL_VERSION_OVERRIDE

每批修复后都重新构建。重复此过程,直到构建通过。

步骤 4:处理行为变更

行为变更不会导致生成错误,但可能改变运行时行为。请逐项检查所有适用项,并确定是否依赖过之前的行为。

高影响行为变更(优先检查):

  1. 已移除 SIGTERM 信号处理 — .NET 运行时不再注册默认的 SIGTERM 处理程序。如果你依赖在收到 SIGTERM 时触发 AppDomain.ProcessExit 或 AssemblyLoadContext.Unloading:

    • ASP.NET Core 和 Generic Host 应用不受影响(它们会注册自己的处理程序)
    • 未使用 Generic Host 的控制台应用和容器化应用必须显式注册 PosixSignalRegistration.Create(PosixSignal.SIGTERM, _ => Environment.Exit(0))
  2. BackgroundService.ExecuteAsync 完全在后台线程上运行 — 首次 await 之前的同步部分不再阻塞启动。如果启动顺序很重要,请将相关代码移至 StartAsync 或构造函数中,或者实现 IHostedLifecycleService。

  3. 现在会保留配置中的 null 值 — JSON null 值不再转换为空字符串。使用非默认值初始化的属性会被 null 覆盖。请检查配置绑定代码。

  4. Microsoft.Data.Sqlite 的 DateTimeOffset 变更(均为高影响):

    • GetDateTimeOffset 在值不带偏移量时现在假定时区为 UTC(此前假定为本地时区)
    • 将 DateTimeOffset 写入 REAL 列时,现在会先转换为 UTC
    • GetDateTime 在值带偏移量时,现在返回 DateTimeKind.Utc 的 UTC 时间
    • 缓解方法:将 AppContext.SetSwitch("Microsoft.Data.Sqlite.Pre10TimeZoneHandling", true) 用作临时解决办法
  5. EF Core 参数化集合 — 集合上的 .Contains() 现在使用多个标量参数,而不是 JSON/OPENJSON。可能会影响大型集合的查询性能。缓解方法:使用 UseParameterizedCollectionMode(ParameterTranslationMode.Parameter) 恢复原行为。

  6. Azure SQL 上 EF Core 的 JSON 数据类型 — Azure SQL 且兼容级别 ≥170 时,现在使用 json 数据类型,而不是 nvarchar(max)。系统会生成迁移来更改现有列。缓解方法:将兼容级别设为 160,或显式使用 HasColumnType("nvarchar(max)")。

  7. System.Text.Json 属性名称冲突验证 — 属性与元数据名称($type、$id、$ref)冲突的多态类型现在会引发 InvalidOperationException。请为冲突的属性添加 [JsonIgnore]。

需要检查的其他行为变更:

  • BufferedStream.WriteByte 不再隐式刷新 — 如有需要,请显式调用 Flush()
  • 默认跟踪上下文传播器已更新为 W3C 标准
  • DriveInfo.DriveFormat 返回实际的 Linux 文件系统类型名称
  • LDAP DirectoryControl 解析更加严格
  • 默认 .NET 容器映像已从 Debian 切换为 Ubuntu(不再提供 Debian 映像)
  • 默认情况下,单文件应用不再在可执行文件目录中查找本机库
  • DllImportSearchPath.AssemblyDirectory 只会搜索程序集目录
  • MailAddress 会验证是否存在连续句点
  • 浏览器 HTTP 客户端默认启用流式 HTTP 响应
  • 已移除 Uri 长度限制 — 如果曾使用 Uri 拒绝不可信来源的超长输入,请添加显式长度验证
  • 对已知 API 端点禁用 Cookie 登录重定向(ASP.NET Core)
  • XmlSerializer 不再忽略带有 [Obsolete] 的属性 — 请检查过时属性中是否包含敏感数据,并添加 [XmlIgnore] 以防止意外暴露数据
  • dotnet restore 会审计传递依赖包
  • dotnet watch 改为向 stderr 而不是 stdout 写入日志
  • dotnet CLI 命令会将与命令无关的数据记录到 stderr
  • 各类 NuGet 行为变更(请参阅 references/sdk-msbuild-dotnet9to10.md)
  • StatusStrip 默认使用 System RenderMode(WinForms)
  • 已修复 TreeView 复选框图像截断问题(WinForms)
  • 错误使用 DynamicResource 会导致崩溃(WPF)
步骤 5:更新基础设施
  1. Dockerfiles:更新基础镜像。默认标签现在使用 Ubuntu,而不是 Debian。对于 .NET 10,不再提供 Debian 镜像。

    # Before
    FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
    FROM mcr.microsoft.com/dotnet/aspnet:9.0
    # After
    FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
    FROM mcr.microsoft.com/dotnet/aspnet:10.0
    
  2. CI/CD 管道:更新 SDK 版本引用。如果使用 global.json,请更新:

    {
      "sdk": {
        "version": "10.0.100"
      }
    }
    
  3. 环境变量已重命名:

    • DOTNET_OPENSSL_VERSION_OVERRIDE 替代旧名称
    • DOTNET_ICU_VERSION_OVERRIDE 替代旧名称
    • NUGET_ENABLE_ENHANCED_HTTP_RETRY 已移除
  4. OpenSSL 要求:现在 Unix 上需要 OpenSSL 1.1.1 或更高版本。macOS 上不再支持 OpenSSL 加密原语。

  5. 解决方案文件格式:如果脚本中使用了 dotnet new sln,请注意它现在会生成 SLNX 格式。如果需要旧格式,请传入 --format sln。

步骤 6:验证
  1. 执行完整的干净构建:dotnet build --no-incremental
  2. 运行所有测试:dotnet test
  3. 如果应用已容器化,请构建并测试容器镜像
  4. 对应用进行冒烟测试,特别关注:
    • 信号处理/正常关闭行为
    • 后台服务启动顺序
    • 对 null 值的配置绑定
    • 使用 Sqlite 处理日期/时间
    • 多态类型的 JSON 序列化
    • 对集合使用 .Contains() 的 EF Core 查询
  5. 安全审查——确认迁移没有削弱安全控制:
    • SslStream API 迁移后,TLS 密码套件验证逻辑仍然保留(SYSLIB0058)
    • 排除包含敏感数据的过时属性,避免其被序列化([XmlIgnore]、[JsonIgnore])
    • 如果曾将 Uri 用作长度限制,输入验证仍会拒绝超长 URI
    • 异常处理程序在返回 true 前会发出与安全相关的遥测数据(身份验证失败、访问违规)
    • 连接字符串设置了明确的 Application Name,且不会泄露版本信息
    • 处理 dotnet restore 漏洞审计发现的问题,而不是将其忽略
  6. 检查差异,确保没有引入意外的行为变更

参考文档

references/ 文件夹包含按技术领域整理的详细重大变更信息。只加载与待迁移项目相关的参考资料:

参考文件加载时机
references/csharp-compiler-dotnet9to10.md始终加载(C# 14 编译器重大变更——field 关键字、extension 关键字、span 重载)
references/core-libraries-dotnet9to10.md始终加载(适用于所有 .NET 10 项目)
references/sdk-msbuild-dotnet9to10.md始终加载(SDK 和构建工具变更)
references/aspnet-core-dotnet9to10.md项目使用 ASP.NET Core
references/efcore-dotnet9to10.md项目使用 Entity Framework Core 或 Microsoft.Data.Sqlite
references/cryptography-dotnet9to10.md项目使用 System.Security.Cryptography 或 X.509 证书
references/extensions-hosting-dotnet9to10.md项目使用 Generic Host、BackgroundService 或 Microsoft.Extensions.Configuration
references/serialization-networking-dotnet9to10.md项目使用 System.Text.Json、XmlSerializer、HttpClient 或网络 API
references/winforms-wpf-dotnet9to10.md项目使用 Windows Forms 或 WPF
references/containers-interop-dotnet9to10.md项目使用 Docker 容器、单文件发布或本机互操作(P/Invoke)

评论

支持 Markdown