EF Core 数据库架构同步策略与实战
Entity Framework Core 提供了两种核心机制来维护数据模型与数据库结构的一致性。选择哪种方案取决于项目以哪一方作为权威来源:
- 模型优先(Code First):通过迁移(Migration)逐步将模型变更应用到数据库,适合迭代频繁的小型项目
- 数据库优先(Database First):通过反向工程(Reverse Engineering)从现有库生成实体类,适合已有成熟数据库的中大型系统
一、数据迁移实战
迁移机制允许以增量方式更新数据库结构,同时保留现有数据。其核心流程如下:
- 开发者执行命令生成迁移文件,描述模型与当前状态的差异
- 迁移文件纳入版本控制,支持团队协作
- 执行更新命令时,EF Core 通过
__EFMigrationsHistory表追踪已应用的变更
工具安装配置
推荐使用跨平台的 .NET CLI 工具:
# 全局安装
dotnet tool install -g dotnet-ef --version 8.0.0
# 后续更新
dotnet tool update -g dotnet-ef
# 项目依赖
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools
# 验证
dotnet ef
常用参数速查:
| 参数 | 简写 | 作用 |
|---|---|---|
--context | -c | 指定 DbContext 类(多上下文场景必需) |
--project | -p | 目标项目路径 |
--startup-project | -s | 启动项目路径 |
--no-build | 跳过编译(确保已最新构建) | |
--verbose | -v | 详细输出 |
Visual Studio 用户可选用包管理器控制台:
Install-Package Microsoft.EntityFrameworkCore.Tools
Get-Help about_EntityFrameworkCore
首个迁移创建
假设存在如下实体:
public class Article
{
public int ArticleId { get; set; }
public string Title { get; set; } = string.Empty;
}
生成初始迁移:
# CLI 方式
dotnet ef migrations add InitialSchema
# 包管理器控制台
Add-Migration InitialSchema
EF Core 将在项目根目录创建 Migrations 文件夹,包含三个关键文件:
XXXXXXXXXXXXXX_InitialSchema.cs:具体的 Up/Down 操作XXXXXXXXXXXXXX_InitialSchema.Designer.cs:迁移元数据AppDbContextModelSnapshot.cs:当前模型快照
应用至数据库:
dotnet ef database update # CLI
Update-Database # VS 控制台
模型迭代演进
需求变更:为 Article 添加发布时间字段
public class Article
{
public int ArticleId { get; set; }
public string Title { get; set; } = string.Empty;
public DateTimeOffset PublishedAt { get; set; }
}
生成差异迁移:
dotnet ef migrations add AddArticlePublishedTime
EF Core 自动比对模型快照,识别新增字段并生成相应的 ALTER TABLE 语句。再次执行 database update 即可同步。
高级迁移技巧
排除特定表(EF Core 5.0+):
跨上下文共享表时,避免重复生成迁移:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<SharedEntity>()
.ToTable("SharedTable", t => t.ExcludeFromMigrations());
}
自定义输出路径:
dotnet ef migrations add Init --output-dir Data/Migrations --namespace MyApp.Data.Migrations
迁移管理:
dotnet ef migrations list # 查看所有迁移
dotnet ef migrations remove # 删除最新未应用的迁移(已应用则失败)
迁移重置(谨慎操作):
- 删除
Migrations目录 - 清空数据库
__EFMigrationsHistory表 - 创建新的初始迁移
dotnet ef migrations add ConsolidatedInit - 生成 SQL 脚本,提取其中的 INSERT 语句
- 手动向历史表插入该迁移记录(标记为已执行)
⚠️ 警告:重置会丢失所有自定义迁移代码,需提前备份复杂的数据操作逻辑。
二、生产环境部署策略
直接执行 database update 仅适合开发环境。生产部署推荐生成 SQL 脚本:
dotnet ef migrations script # 完整脚本:空库 → 最新
dotnet ef migrations script 0 # 同上,显式指定起始
dotnet ef migrations script 20240101000000_AddFeature # 从指定版本到最新
脚本优势:
- 可人工审核,避免误删数据
- 支持 DBA 审核与版本归档
- 集成 CI/CD 流水线
三、反向工程(Database First)
从现有数据库生成实体类和上下文:
前置条件
- 安装对应数据库的 EF Core 提供程序(如
Microsoft.EntityFrameworkCore.SqlServer) - 确保
Microsoft.EntityFrameworkCore.Design已引用
基础命令
dotnet ef dbcontext scaffold "Server=.;Database=BlogDb;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer
Visual Studio 等效命令:
Scaffold-DbContext 'Server=.;Database=BlogDb;Trusted_Connection=True;' Microsoft.EntityFrameworkCore.SqlServer
精细控制选项
| 功能 | CLI 参数 | PMC 参数 |
|---|---|---|
| 指定表 | --table Users --table Posts | -Tables Users,Posts |
| 指定架构 | --schema dbo --schema sales | -Schemas dbo,sales |
| 保留原名 | --use-database-names | -UseDatabaseNames |
| 上下文名称 | --context BlogContext | -Context BlogContext |
| 实体输出目录 | --output-dir Entities | -OutputDir Entities |
| 上下文输出目录 | --context-dir Data | -ContextDir Data |
| 命名空间 | --namespace MyApp.Core | -Namespace MyApp.Core |
| 上下文命名空间 | --context-namespace MyApp.Data | -ContextNamespace MyApp.Data |
完整示例:
dotnet ef dbcontext scaffold "连接字符串" Microsoft.EntityFrameworkCore.SqlServer \
--context AppDbContext \
--context-dir Data \
--output-dir Domain/Entities \
--namespace MyProject.Domain \
--context-namespace MyProject.Data \
--table Articles \
--table Categories \
--use-database-names
注意:PowerShell 中需对
$字符转义,而非反斜杠。
四、方案选型建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 全新项目,团队熟悉 ORM | Code First 迁移 | 版本控制友好,迭代灵活 |
| 遗留系统,数据库已成熟 | Database First | 快速接入,避免重构风险 |
| DBA 主导,变更需审批 | 迁移 + SQL 脚本 | 可审计,符合合规要求 |
| 微服务,多团队共享库 | 混合策略 | 核心表反向工程,扩展字段迁移管理 |