-
EF Core迁移——c#开发数据库版本控制
第一部分:C#基础入门
EF Core迁移——数据库版本控制
实例介绍
EF Core迁移是数据库版本控制的核心工具,它能自动生成数据库结构变更的SQL脚本,同步实体模型与数据库表结构,避免手动编写SQL的错误,同时支持团队协作时统一数据库版本。本节通过“用户权限系统”的数据库迭代场景,带你掌vb.net教程C#教程python教程SQL教程access 2010教程握迁移的全流程:创建迁移、应用到数据库、回滚版本、自定义迁移逻辑、多环境配置,让你彻底解决“数据库结构不一致”的痛点。
需求分析
设计一个支持版本控制的数据库迭代方案,核心需求:
1.初始化迁移:从实体模型生成初始数据库结构;
2.迭代迁移:修改实体后生成增量变更脚本;
3.版本回滚:回滚到指定的数据库版本;
4.自定义迁移:添加初始数据、创建索引/存储过程;
5.多环境适配:开发/生产环境使用不同的连接字符串;
6.脚本生成:导出迁移的SQL脚本(用于生产环境手动执行)。
代码实现
前置条件:
复用之前的User实体,新增Role实体(演示迁移迭代);
安装EF Core工具:dotnet tool install --global dotnet-ef;
项目引用:Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.SqlServer、Microsoft.Extensions.Configuration.Json(多环境配置)。
-
准备实体与DbContext
csharp
// 新增Role实体(演示迁移迭代)
public class Role {
public int Id { get; set; }
public string RoleName { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
}
// 升级DbContext(添加Role DbSet)
public class UserDbContext : DbContext {
private readonly IConfiguration _config;
public UserDbContext(IConfiguration config) => _config = config;
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; } // 新增
protected override void OnConfiguring(DbContextOptionsBuilder options) {
// 从配置文件读取连接字符串(多环境适配)
options.UseSqlServer(_config.GetConnectionString("DefaultConnection"));
}
protected override void OnModelCreating(ModelBuilder model) {
// User实体配置(复用之前的逻辑)
model.Entity<User>().HasIndex(u => u.Email).IsUnique();
// Role实体配置
model.Entity<Role>().HasIndex(r => r.RoleName).IsUnique();
}
}
-
多环境配置文件
appsettings.json(通用配置):
json
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=(localdb)MSSQLLocalDB;Initial Catalog=UserDB;Integrated Security=True"
}
}
appsettings.Development.json(开发环境):
json
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=(localdb)MSSQLLocalDB;Initial Catalog=UserDB_Dev;Integrated Security=True"
}
}
appsettings.Production.json(生产环境):
json
{
"ConnectionStrings": {
"DefaultConnection": "Server=prod-sql;Database=UserDB_Prod;User Id=sa;Password=***;"
}
}
-
迁移核心操作(CLI命令)
以下命令在项目根目录执行:
| 场景 | 命令 | 说明 |
|---|---|---|
| 初始化迁移 | dotnet ef migrations add InitialCreate | 生成初始迁移文件(含Users/Roles表) |
| 应用到数据库 | dotnet ef database update | 执行迁移,创建数据库结构 |
| 迭代迁移(新增PhoneNumber) | dotnet ef migrations add AddPhoneToUser | 修改User实体后生成增量迁移 |
| 回滚到初始版本 | dotnet ef database update InitialCreate | 回滚到指定迁移版本 |
| 删除未应用的迁移 | dotnet ef migrations remove | 删除最近生成但未应用的迁移文件 |
| 导出SQL脚本(生产用) | dotnet ef migrations script InitialCreate AddPhoneToUser --output migrate.sql | 导出两个迁移之间的SQL脚本 |
-
自定义迁移(添加初始数据)
生成迁移后,手动修改迁移文件的Up方法,添加初始数据:
csharp
// 迁移文件:20240520_AddInitialRoles.cs
public partial class AddInitialRoles : Migration {
protected override void Up(MigrationBuilder migrationBuilder) {
// 自动生成的Role表创建逻辑(略)
// 手动添加初始数据
migrationBuilder.Sql(@"
INSERT INTO Roles (RoleName, Description)
VALUES ('Admin', '系统管理员'), ('User', '普通用户');
");
}protected override void Down(MigrationBuilder migrationBuilder) {
// 自动生成的回滚逻辑(略)
// 手动回滚初始数据
migrationBuilder.Sql("DELETE FROM Roles WHERE RoleName IN ('Admin', 'User');");
}
}
逐行讲解 -
迁移文件结构
每个迁移文件包含两个核心方法:
Up():应用迁移的逻辑(如创建表、添加列);
Down():回滚迁移的逻辑(如删除表、移除列);
示例:InitialCreate.cs的Up方法:
csharp
protected override void Up(MigrationBuilder migrationBuilder) {
migrationBuilder.CreateTable(
name: "Roles",
columns: table => new {
Id = table.Column(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RoleName = table.Column(type: "nvarchar(450)", nullable: false),
Description = table.Column(type: "nvarchar(max)", nullable: false)
},
constraints: table => table.PrimaryKey("PK_Roles", x => x.Id));migrationBuilder.CreateIndex(
name: "IX_Roles_RoleName",
table: "Roles",
column: "RoleName",
unique: true);
}
解释:CreateTable创建Roles表,CreateIndex添加唯一索引(对应模型配置的HasIndex)。 -
模型快照的作用
迁移生成时会同步更新UserDbContextModelSnapshot.cs,它是当前数据库结构的快照。下次执行Add-Migration时,EF Core会对比快照与当前实体模型,生成差异的迁移逻辑。因此,快照文件必须提交到版本控制(如Git),确保团队成员的模型一致。 -
多环境迁移命令
指定环境变量执行迁移(如生产环境):
bashWindows
set ASPNETCORE_ENVIRONMENT=Production && dotnet ef database update
Linux/macOS
ASPNETCORE_ENVIRONMENT=Production dotnet ef database update
解释:通过环境变量加载对应配置文件,使用生产环境的连接字符串。
基础知识拓展 -
迁移原理
EF Core迁移的核心逻辑是模型对比:
1.首次迁移:生成模型快照,记录初始结构;
2.迭代迁移:对比当前模型与快照,生成差异的Up/Down方法;
3.应用迁移:执行Up方法,更新数据库与快照;
4.回滚迁移:执行Down方法,恢复数据库与快照。 -
自定义迁移的常见场景
添加初始数据:如系统角色、管理员账号;
创建存储过程/视图:migrationBuilder.Sql("CREATE PROCEDURE GetUser ...");
修改索引/约束:如添加复合索引、外键约束;
数据迁移:如拆分列、合并表(需手动编写SQL)。 -
迁移最佳实践
1.版本控制:迁移文件与快照必须提交到Git,团队成员同步执行;
2.生产安全:先导出SQL脚本(Script-Migration),检查无误后再手动执行;
3.避免手动修改:不要直接修改数据库结构,所有变更通过迁移实现;
4.测试迁移:在开发环境测试迁移的应用与回滚,确保无错误;
5.命名规范:迁移名称要清晰(如AddPhoneToUser而非Migration1)。 -
迁移常见问题
快照不一致:删除快照文件,重新生成初始迁移(Add-Migration InitialCreate -Force);
生产回滚风险:已应用到生产的迁移不要随意回滚,建议创建新迁移修复问题;
性能优化:大表迁移时,分批次处理数据,避免锁表。
总结
EF Core迁移是数据库版本控制的最佳实践,它将实体模型与数据库结构绑定,自动生成变更脚本,解决了团队协作中数据库不一致的痛点。通过迁移,你可以轻松迭代数据库结构、回滚版本、自定义逻辑,同时适配多环境需求。掌握迁移后,你将告别手动编写SQL的繁琐,专注于实体模型的设计,大幅提升开发效率。
关键takeaway:迁移文件是代码的一部分,必须与项目同步版本控制;生产环境迁移前务必导出SQL脚本检查;自定义迁移是处理复杂场景的利器。
来源:https://www.xin3721.com/ArticlecSharp/c49440.html










