背景
项目初期建表时,没有考虑到后续拓展性,错误地将描述 字段添加到了关系表 ,关系表应该只能存放关系。需要将描述 迁移到寄存器表中。
技术栈:EFCore ORM、SQLite3
概述
本文记录一下迁移的过程,有类似的需求以便参考。
本次迁移一共分为 5 步走:
- 目标表新增描述字段
- 迁移数据库表结构
- 编写、执行脚本复制描述字段数据
- 删除代码中原字段、修改对原字段的引用
- 检查无误后迁移数据表结构
目标表新增描述字段

目标表新增属性 Description
迁移数据库表结构
执行下面的命令
shell
dotnet ef migrations add AddDescriptionToSpecialRegister
dotnet ef database update
现在迁移好的目标表中已有新的字段了。注意这里新的数据库文件位置取决于自己指定的数据库路径:
cs
public class DataContext : DbContext
{
public DataContext()
{
string folder = AppDomain.CurrentDomain.BaseDirectory;
string path = Path.Combine(folder, "data.db");
DbPath = path;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite($"FileName={DbPath}");
}
}
我这里项目属性设置了始终复制源代码中的 data.db 到 bin 目录,所以每次数据库迁移完,要手动替换数据库文件。觉得麻烦就先关掉始终复制,所有迁移完成后再替换;或者开发/迁移阶段直接指定使用源代码中的数据库文件。
编写、执行脚本复制描述字段数据
cs
class Program
{
static void Main()
{
DataContext context = new DataContext();
// 输出当前使用的数据库路径
Console.WriteLine($"当前使用的数据库路径: {context.Database.GetConnectionString()}");
using (var transaction = context.Database.BeginTransaction())
{
try
{
var descriptions = context.CpuSpecialRegisterAssociations.ToList();
foreach (var d in descriptions)
{
var description = d.Description;
var specialRegister = context.SpecialRegisters.First(x => x.Id == d.SpecialRegisterId);
specialRegister.Description = description;
}
context.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
Console.WriteLine($"迁移过程中出错: {ex.Message}");
Console.WriteLine(ex.StackTrace);
}
}
}
}
删除代码中原字段、修改对原字段的引用
删除原表中的描述属性。这时候直接执行dotnet ef migrations add xxxx
会编译不通过,因为很多地方用了这个描述属性,而它被删除了。
修改之前引用这个属性的代码。修改完成后,可以使用 dotnet build
检查一下编译是否通过。
如果编译通过了,就可以进行下一步。
检查无误后迁移数据表结构
执行以下命令
shell
dotnet ef migrations add RemoveDescriptionInCpuSpecialRegisterAssociation
dotnet ef database update
执行完毕后,数据库中关系表中的描述字段就被删掉了。
总结
自此完成了数据库两表之间的数据迁移。可根据自己的情况进行数据库文件的替换(若数据库源文件与修改的文件不是相同的)