在C#项目开发中,数据库架构迁移是迭代过程中不可避免的工作,随着业务需求变化,需要新增表、修改字段、调整索引等,手动执行SQL脚本不仅容易遗漏,还难以追溯变更历史。C#生态中有多种成熟的工具和方案可以完成数据库架构迁移,其中最常用的两种是Entity Framework Core自带的Migrations功能和第三方迁移工具FluentMigrator。

一、使用Entity Framework Core Migrations执行迁移
Entity Framework Core(简称EF Core)是微软官方推出的ORM框架,内置的Migrations功能可以自动根据实体类的变化生成数据库变更脚本,是.NET项目中常用的迁移方案,适合已经使用EF Core作为数据访问层的项目。
1. 基础环境准备
首先需要安装对应的NuGet包,以SQL Server数据库为例,需要安装以下包:
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
2. 定义实体类和数据库上下文
首先创建需要映射的实体类,比如一个简单的用户实体:
// 用户实体类
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public DateTime CreateTime { get; set; }
}
// 数据库上下文类
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// 配置数据库连接字符串,这里使用本地SQL Server示例
optionsBuilder.UseSqlServer("Server=localhost;Database=TestDb;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 可以配置实体和表的映射规则
modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<User>().HasKey(u => u.Id);
}
}
3. 生成并执行迁移
使用EF Core的命令行工具生成迁移文件,执行以下命令:
# 生成迁移文件,InitialCreate是迁移的名称 Add-Migration InitialCreate # 将迁移应用到数据库 Update-Database
执行完成后,EF Core会在项目中生成Migrations文件夹,里面包含迁移的快照和具体的变更逻辑,同时数据库中会创建对应的表,还会生成__EFMigrationsHistory表用于记录已经执行的迁移历史。
如果后续需要修改实体类,比如给User类新增一个Phone字段,只需要再次执行Add-Migration命令生成新的迁移文件,然后执行Update-Database即可完成数据库架构更新。
4. 回滚迁移
如果需要回滚到之前的迁移版本,可以执行以下命令:
# 回滚到指定名称的迁移,比如回滚到InitialCreate之前的状态 Update-Database InitialCreate
二、使用FluentMigrator执行迁移
FluentMigrator是一个轻量级的.NET数据库迁移框架,不依赖特定的ORM,支持多种数据库,通过代码的方式定义迁移逻辑,适合不使用EF Core或者需要更灵活迁移控制的场景。
1. 安装依赖包
以SQL Server为例,安装对应的NuGet包:
- FluentMigrator
- FluentMigrator.Runner
- FluentMigrator.Runner.SqlServer
2. 定义迁移类
FluentMigrator通过继承Migration类来定义每一次的迁移逻辑,每个迁移类需要指定唯一的版本号:
using FluentMigrator;
// 第一个迁移,版本号20240101000001
[Migration(20240101000001)]
public class InitialDatabaseMigration : Migration
{
public override void Up()
{
// 创建Users表
Create.Table("Users")
.WithColumn("Id").AsInt32().PrimaryKey().Identity()
.WithColumn("UserName").AsString(50).NotNullable()
.WithColumn("Email").AsString(100).NotNullable()
.WithColumn("CreateTime").AsDateTime().NotNullable();
}
public override void Down()
{
// 回滚时删除Users表
Delete.Table("Users");
}
}
// 第二个迁移,新增Phone字段,版本号20240101000002
[Migration(20240101000002)]
public class AddPhoneColumnMigration : Migration
{
public override void Up()
{
Alter.Table("Users")
.AddColumn("Phone").AsString(20).Nullable();
}
public override void Down()
{
Delete.Column("Phone").FromTable("Users");
}
}
3. 执行迁移
在程序启动时配置并执行迁移,示例代码如下:
using FluentMigrator.Runner;
using Microsoft.Extensions.DependencyInjection;
using System;
class Program
{
static void Main(string[] args)
{
var serviceProvider = CreateServices();
using (var scope = serviceProvider.CreateScope())
{
// 执行迁移
var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();
runner.MigrateUp();
}
}
private static IServiceProvider CreateServices()
{
return new ServiceCollection()
// 添加FluentMigrator服务
.AddFluentMigratorCore()
.ConfigureRunner(rb => rb
// 指定数据库类型为SQL Server
.AddSqlServer()
// 配置数据库连接字符串
.WithGlobalConnectionString("Server=localhost;Database=TestDb;Trusted_Connection=True;")
// 扫描当前程序集中所有的迁移类
.ScanIn(typeof(InitialDatabaseMigration).Assembly).For.Migrations())
.BuildServiceProvider(false);
}
}
执行程序后,FluentMigrator会自动执行所有未应用的迁移,同时在数据库中生成VersionInfo表记录迁移版本信息。如果需要回滚,可以调用runner.MigrateDown(版本号)方法回滚到指定版本。
三、两种方案的对比
两种方案各有适用场景,具体对比如下:
| 对比项 | EF Core Migrations | FluentMigrator |
|---|---|---|
| 依赖条件 | 需要项目使用EF Core作为ORM | 无ORM依赖,可独立使用 |
| 迁移定义方式 | 基于实体类自动生成 | 手动编写迁移代码 |
| 数据库支持 | 支持EF Core适配的所有数据库 | 支持主流关系型数据库 |
| 灵活性 | 适合常规表结构变更,复杂变更需要手动调整 | 迁移逻辑完全自定义,灵活性更高 |
| 学习成本 | 使用EF Core的项目学习成本低 | 需要了解迁移类的编写规则 |
四、注意事项
- 生产环境执行迁移前,一定要在测试环境验证迁移脚本的正确性,避免数据丢失。
- 迁移文件的命名要清晰,方便后续追溯变更内容。
- 如果项目中多人协作开发,需要注意迁移文件的版本冲突问题,尤其是EF Core的Migrations文件,合并代码时需要仔细检查。
- 对于已经上线的生产数据库,尽量不要删除已有的迁移文件,避免回滚时出现错误。
C#数据库架构迁移Entity_Framework_CoreMigrationsFluentMigrator修改时间:2026-07-21 23:42:36