一. 管理数据库架构概述
EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步. 一是以 EF Core 模型为基准, 二是以数据库为基准.
(1) 如果希望以 EF Core 模型为准, 请使用迁移. 对 EF Core 模型进行更改时, 此方法会以增量方式将相应架构更改应用到数据库, 以使数据库保持与 EF Core 模型兼容.
(2) 如果希望以数据库架构为准, 请使用反向工程. 使用此方法, 可通过将数据库架构反向工程到 EF Core 模型来生成相应的 DbContext 和实体类型.
1.1. 迁移概述
在开发期间, 数据模型发生更改后, 会与数据库不同步. 虽然可以删除该数据库, 让 EF 创建一个新的数据库来匹配该模型, 但此过程会导致数据丢失. 迁移作用是指: 在 EF Core 中使用迁移功能, 能够以递增方式更新数据库架构, 使其与应用程序的数据模型保持同步, 同时保留数据库中的现有数据.
迁移包括 命令行工具和 API, 可协助执行以下任务:
(1) 创建迁移. 生成数据库更新的代码脚本, 用来准备将应用模型同步到数据库.
(2) 更新数据库. 通过 "创建迁移" 的代码脚本, 同步数据库.
(3) 自定义迁移代码. 有时需要修改或补充应用模型, 并同步数据库.
(4) 删除迁移. 删除生成的迁移版本 (该版本没有更新到数据库).
(5) 还原迁移. 撤消回滚数据库更改 (该版本已更新到数据库).
(6) 生成 SQL 脚本. 可能需要一个脚本来更新生产数据库, 或者对迁移代码进行故障排除.
(7) 在运行时应用迁移. 如果在设计期间更新和运行脚本不是最佳选项时, 可在运行时调用 Migrate() 方法.
2.1 安装命令工具
(1) 对于 Visual Studio 开发, 建议使用 Package Manager Console(程序包管理器控制台) 工具, 使用 Windows 上的 PowerShell 脚本.
(2) 对于其他开发环境, 请选择. NET Core CLI 工具, 使用 dotnet 命令是跨平台的.
本篇使用 Visual Studio 开发, 使用 Package Manager Console 工具来进行迁移管理, 用 PowerShell 脚本, 并附带上跨平台管理 的 dotnet 命令. 还是使用 Blog 和 Post 应用模型来演示.
二. 命令演示
2.1 创建迁移
在定义初始化模型后, 即应创建数据库. 若要添加初始迁移, 请运行以下命令, 其中 InitialCreate 属于自定义迁移类名, 它继承了 DbContext.
PowerShell | dotnet |
Add-Migration InitialCreate | dotnet ef migrations add InitialCreate |
关于准备工作和创建迁移注意事项这里不在说明, 请参考 "asp.net core 系列 20 EF 基于数据模型创建数据库". 在开发中, 一般都是使用多层架构, 这里新建了一个实体类库 EFGetStarted.AspNetCore.Model, 在 web 项目的 "依赖项" 上右击添加引用, 选择实体类库.
在实体类库上安装数据库提供程序. 创建三个类 BloggingContext 类 (继承 DbContext),Blog 实体类, Post 实体类. 接着使用 Package Manager Console 工具运行 Add-Migration InitialCreate 命令. 如下所图所示:
当运行了 Add-Migration InitialCreate 后, 将在项目中生成一个 Migrations 文件夹, 并在其中生成三个文件, 文件名中的时间戳有助于保证文件按时间顺序排列:
(1) 00000000000000_InitialCreate.cs-- 主迁移文件. 包含应用迁移所需的操作 Up() 和还原迁移所需的操作 Down() .
(2) 00000000000000_InitialCreate.Designer.cs-- 迁移元数据文件. 包含 EF 所用的信息, 如给实体类型构建属性, 主键, 外键, 索引, 映射到数据表, 主体和依赖关系等等, 如下所示:
(3) BloggingContextModelSnapshot.cs - 当前模型的快照. 用于确定添加下一次迁移时更改的内容 (用于递增更新).
2.2 更新数据库
接下来, 将迁移应用于数据库以创建架构. 命令如下:
PowerShell | dotnet |
Update-Database InitialCreate | dotnet ef database update InitialCreate |
注意: 更新到数据库, 需要创建数据库的连接. 项目中配置数据库连接, 一般是存放在 Web 项目的 appsettings.JSON 文件中, 并在 Startup 类中调用. 这里演示是直接写死在 Startup 类代码中, 如下所示:
- var connection = "Data Source = {ip}; Initial Catalog = EFGetStarted.AspNetCore.NewDb; User ID = hsr;Password =js*2015;";
- services.AddDbContext<BloggingContext>
- (options => options.UseSqlServer(connection));
在 Package Manager Console 工具中, 运行 Update-Database InitialCreate 命令, 同步到数据库, 如下所示:
2.3 自定义迁移代码
更改 EF Core 模型后, 数据库架构可能不同步. 为使其保持最新, 请再添加一个新的迁移. 例如我在 Blog 实体类, 新添加了一个属性, 和修改了一个属性的 CLR 类型.
- public class Blog
- {
- public int BlogId { get; set; }
- // 将 string 改为 char
- public char Name { get; set; }
- // 新增一个属性
- public string Title { get; set; }
- public string Url { get; set; }
- public ICollection<Post> Posts { get; set; }
- }
运行 Add-Migration Blog_Modifier, 添加一个新的迁移
再运行 Update-Database Blog_Modifier, 同步到数据库中. char 类型的 Name 生成后默认是 nvarchar(1), 对于指定属性的长度, 参考上篇关系数据库建模.
查看数据库的迁移历史, 可以查看到迁移 ID MigrationId, 其中 20190222031152_Blog_Modifier 是最新的迁移同步到数据库的版本.
2.3.1 空迁移
有时模型未变更, 直接添加迁移也很有用处. 在这种情况下, 添加新迁移会创建一个带空类的代码文件. 可以自定义此迁移, 执行与 EF Core 模型不直接相关的操作. 可能需要通过此方式管理的一些事项包括:
(1) 全文搜索
(2) 函数
(3) 存储过程
(4) 触发器
(5) 视图
通过上面操作, 以 Code First 模式下, 不需要对数据库进行直接操作, 在数据库建模上, DBA 以检查数据库架构为主.
2.4 删除迁移
有时修, 项目在添加迁移后, 意识到需要在应用迁移前对 EF Core 模型作出其他更改. 要删除上个迁移. 删除迁移是使用了 Add-Migration 生成迁移后, 还没有应用 Update-Database 同步到数据库架构. 请使用如下命令.
PowerShell | dotnet |
Remove-Migration Name | dotnet ef migrations remove Name |
2.5 还原迁移
如果已经对数据库应用一个迁移 (或多个迁移), 但需将其复原 (回滚), 需要使用更新数据库命令, 并指定回滚时的目标迁移名称. 下面还原到迁移名称 InitialCreate 状态时. 运行 PM> Update-Database InitialCreate 后, 数据库同步, 回到了最初 InitialCreate 迁移状态, 数据库 Blogs 表还原到了当初.
2.6 生成 SQL 脚本
调试迁移或将其部署到生产数据库时, 生成一个 SQL 脚本很有帮助. 之后可进一步检查该脚本的准确性, 并对其作出调整以满足生产数据库的需求. 该脚本还可与部署技术结合使用. 基本命令如下.
PowerShell | dotnet |
Script-Migration | dotnet ef migrations script |
Script-Migration 参数介绍:
-From<String> | 开始迁移。迁移可以通过名称或 ID 来标识。数字 0 是一种特殊情况,这意味着在第一次迁移之前。默认值为 0 |
-To<String> | 结束迁移。默认值为最后一次迁移。 |
-Idempotent | 生成可在任何迁移时在数据库上使用的脚本。 |
-Output <String> | 要将结果写入的文件。如果省略该参数,则在创建应用程序运行时文件的文件夹中使用生成的名称创建文件,例如:/obj/Debug/netcoreapp2.1/ghbkztfz.sql/ |
下面的示例使用 InitialCreate 迁移版本, 创建一个 sql 脚本文件, 输出到 D 盘.
PM> Script-Migration -From 0 -To InitialCreate -Output D:\InitialCreate.sql
- IF OBJECT_ID(N'[__EFMigrationsHistory]') IS NULL
- BEGIN
- CREATE TABLE [__EFMigrationsHistory] (
- [MigrationId] nvarchar(150) NOT NULL,
- [ProductVersion] nvarchar(32) NOT NULL,
- CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
- );
- END;
- GO
- CREATE TABLE [Blogs] (
- [BlogId] int NOT NULL IDENTITY,
- [Name] nvarchar(max) NULL,
- [Url] nvarchar(max) NULL,
- CONSTRAINT [PK_Blogs] PRIMARY KEY ([BlogId])
- );
- GO
- CREATE TABLE [Posts] (
- [PostId] int NOT NULL IDENTITY,
- [Title] nvarchar(max) NULL,
- [Content] nvarchar(max) NULL,
- [BlogId] int NOT NULL,
- CONSTRAINT [PK_Posts] PRIMARY KEY ([PostId]),
- CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blogs] ([BlogId]) ON DELETE CASCADE
- );
- GO
- CREATE INDEX [IX_Posts_BlogId] ON [Posts] ([BlogId]);
- GO
- INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
- VALUES (N'20190222024519_InitialCreate', N'2.2.1-servicing-10028');
- GO
- View Code
2.7 在运行时应用迁移
某些应用程序可能希望在启动或首次运行期间在运行时应用迁移. 使用该 Migrate() 方法执行此操作.
myDbContext.Database.Migrate();
注意: 此方法并不适合所有场景. 尽管此方法非常适合具有本地数据库的应用, 但是大多数应用程序需要更可靠的部署策略, 例如生成 SQL 脚本.
请勿在 Migrate() 前调用 EnsureCreated(). EnsureCreated() 会绕过迁移创建架构, 这会导致 Migrate() 失败.
参考文献:
EF 迁移
Package Manager Console
来源: https://www.cnblogs.com/MrHSR/p/10417484.html