AIGC标识 排除 EF Core Migrations 自动生成文件提升编译优化速度

一、问题背景

当前一个基于 ABP 框架的大规模 .NET 项目(4-5M行代码),目标框架是 net5.0。解决方案里包含多个项目,比如:

  • XXX.XXX.Web:Web 宿主项目,有 Program.cs,负责启动应用。
  • XXX.XXX.StockManage.HttpApi:HTTP API 模块,是一个类库,没有 Program.cs。
  • XXX.EFCoreMigration.Shared:EF Core 迁移共享项目,里面存放数据库迁移文件。

项目经过多次迭代,EF Core 的 Migrations 目录下积累了很多迁移文件。每个迁移通常包含:

  • xxxx_MigrationName.cs:迁移逻辑。
  • xxxx_MigrationName.Designer.cs:迁移元数据。
  • XxxDbContextModelSnapshot.cs:当前数据库模型的快照。

日常开发使用 Debug 配置编译。编译速度越来越慢,改一点代码重新编译也要等很久。后来修改了两个 .csproj 文件,编译速度明显变快。这篇文章记录一下原因和做法。

二、原因

编译变慢主要有两个方面的原因。

1. EF Core 的 .Designer.cs 和 ModelSnapshot.cs 代码量很大

EF Core 每次执行 Add-Migration 都会生成 .Designer.cs 文件。ModelSnapshot.cs 也会在迁移过程中更新。这些文件会把整个 DbContext 的模型信息展开成 C# 代码。

例如,里面会有每个实体、每个属性、每个索引、每个外键的配置。一个中等规模的项目,单个 ModelSnapshot.cs 可能几万行。如果迁移文件很多,所有 .Designer.cs 加在一起可能几十万行。

这些文件默认会参与编译。C# 编译器需要对这些代码做词法分析、语法分析、语义绑定、生成 IL。代码量越大,编译时间越长。每次 Debug 构建都会重新处理这些文件,增量编译也会受影响。

2. .NET SDK 和一些 NuGet 包会带来额外构建开销

项目目标框架是 net5.0,这个版本已经停止支持。新版 .NET SDK 在构建时会检查目标框架是否 EOL,还会检查 workload 是否 EOL。这些检查每次构建都会执行,带来固定开销。

另外,NuGet 包除了程序集,还可能带有 build 和 buildTransitive 目录下的 .props 和 .targets 文件。MSBuild 会自动导入这些文件,可能注册额外的 Target、代码生成任务或分析器。这些也会增加构建时间。

三、解决逻辑

解决思路是:日常开发编译不需要迁移的 .Designer.cs 文件。这些文件只在执行 dotnet ef migrations add 或 dotnet ef database update 时才需要。所以可以在 Debug 配置下把它们从编译项中排除。

同时,关闭 SDK 的 EOL 检查、workload 检查,减少每次构建的固定开销。对于确认不需要 build 逻辑的包,排除 build 和 buildTransitive 资源,减少 MSBuild 节点。

这样做的目的是:让 Debug 构建只编译真正需要修改和运行的代码,把不参与日常开发的自动生成文件排除掉。

四、解决方案

修改了两个 .csproj 文件。

1. XXX.EFCoreMigration.Shared.csproj

在 PropertyGroup 中增加:

<DefaultItemExcludes Condition="'$(Configuration)' == 'Debug' ">$(DefaultItemExcludes);Migrations\**\*.Designer.cs</DefaultItemExcludes>
<DefaultItemExcludes Condition="'$(Configuration)' == 'Debug' ">$(DefaultItemExcludes);Migrations\**\**\*.Designer.cs</DefaultItemExcludes>

这两行的作用是:在 Debug 配置下,把 Migrations 目录下所有 .Designer.cs 文件排除出编译。第一条覆盖一级子目录,第二条覆盖多级子目录。Release 配置下不排除,避免影响迁移生成。

2. XXX.XXX.Web.csproj

在 PropertyGroup 中增加:

<DisableGclm>true</DisableGclm>
<CheckEolWorkloads>false</CheckEolWorkloads>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<DisableEolTargetFrameworkWarning>true</DisableEolTargetFrameworkWarning>
<ExcludeAssets>build,buildTransitive</ExcludeAssets>

这些设置的作用:

  • CheckEolTargetFramework、CheckEolWorkloads、DisableEolTargetFrameworkWarning:关闭目标框架 EOL 检查,减少警告和检查任务。
  • DisableGclm:关闭 MSBuild 的一个内部开关,减少编译器内部开销。
  • SuppressTfmSupportBuildWarnings:减少构建日志输出。
  • ExcludeAssets=build,buildTransitive:排除 NuGet 包的 build 资源,减少 MSBuild 导入和执行的任务。

注意:ExcludeAssets 要谨慎使用。如果某个包依赖自己的 build targets 才能工作,排除后可能会出问题。

五、可能仍然存在的困境

这些修改能加快编译,但也有一些需要注意的地方。

  1. 排除 .Designer.cs 后,不能在排除的项目里直接执行 dotnet ef migrations add。生成迁移时 EF Tools 需要这些文件参与编译。通常做法是到专门的迁移项目执行,或者切换到 Release 配置。

  2. ExcludeAssets=build,buildTransitive 是项目级设置,会影响所有引用的包。如果发现某个包功能异常,比如源生成器不工作、某个 Target 没执行,要排查是不是被这条设置干掉了。

  3. 这些优化主要针对 Debug 构建。Release 或 CI 发布时是否保留,取决于团队是否需要发布包执行迁移。我们目前在 Debug 下排除,Release 保留。

  4. 编译速度慢可能还有其他原因,比如大量分析器、源生成器、项目引用太多、增量编译失效等。这次优化只是减少了一部分开销,不是解决所有问题。

  5. 如果以后升级到 net6.0 或更高版本,EOL 检查相关的设置可能不再必要,但排除 .Designer.cs 的做法仍然有效。

  6. 需要团队统一约定,避免有人在 Debug 下执行迁移命令导致报错。

总结

这次编译速度优化中,收益最大的是排除 EF Core 迁移的 .Designer.cs 文件。这些文件代码量很大,日常开发又不需要参与编译。关闭 SDK 的额外检查和 NuGet 包的 build 资源也有帮助,但量级小一些。整体思路是:找出不必要参与构建的内容,把它们从 Debug 构建中移除。

posted @ 2026-09-27 17:34  秦晓  阅读(5)  评论(0)    收藏  举报