最近打算用.NET Core寫一份開源的簡易CMS系統,來練練手
所以又去深入研究了一下Entity Framework Core
發現其實有些細節園子里還是很少講到.
特意整理了幾個細節.
1.數據庫遷移
先了解一下什么是"數據庫遷移",它提供了一種方法,可以逐步將Code First的實體架構更改應用於數據庫,以保持數據庫與EF Core模型同步,同時保留數據庫中的現有數據。
EF Core的數據遷移相對EF6來說改了不少也簡化了一些.所以我們現在就來看看如何進行數據遷移
我們以官方代碼來做為例子..先來創建一個簡單的上下文.
public class BloggingContext : DbContext { public BloggingContext() : base() { } private static ILoggerFactory Mlogger => new LoggerFactory(); protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { Mlogger.AddProvider(new MyFilteredLoggerProvider()); var loggerFactory = optionsBuilder .UseMySql(@"鏈接地址"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { } public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } [MaxLength(50)] public string Title { get; set; } public string Content { get; set; } public int? BlogId { get; set; } public Blog Blog { get; set; } } }
然后我們通過Nuget來添加引用.
Microsoft.EntityFrameworkCore.Tools
打開NuGet包管理控制台
選擇默認項目為實體上下文所在的程序集如下:
首先我們需要添加一個遷移版本.
執行命令如下:
Add-Migration BanBen1(這里是版本的名稱,可以自己定義)
我們會發現Model程序集下多了一個文件夾為Migrations里面有3個文件.如下:
- XXXXXXXXXXXXX_BanBen1.cs - 主遷移文件。包含應用遷移(in
Up()
)和恢復(inDown()
)所需的操作。 - XXXXXXXXXXXXX_BanBen1.Designer.cs - 遷移元數據文件。包含EF使用的信息。
- BloggingContextModelSnapshot.cs - 當前模型的快照。主要用於確定添加下一次遷移時發生了哪些變化.
然后我們執行命令
Update-Database
如果你的數據庫沒創建,是第一次,就會執行成功,
如果你前期創建過數據庫.但是是第一次創建遷移..就會失敗.(注意這里!!)
因為第一次生成的遷移方法是按照新增來遷移的..而不是修改.
錯誤信息可能會如圖:
解決方法是找到XXXXXXXXXXXXX_BanBen1.cs - 主遷移文件,刪除Up和Down里面的代碼.
刪除后如下:
public partial class BanBen1 : Migration { protected override void Up(MigrationBuilder migrationBuilder) { } protected override void Down(MigrationBuilder migrationBuilder) { } }
其實這次遷移就沒有修改數據庫任何信息..
我們在來創建第二個遷移版本..
首先,我們修改實體類..給Post的Content加上長度限制,如下:
public class Post { public int PostId { get; set; } [MaxLength(50)] public string Title { get; set; } [MaxLength(50)] public string Content { get; set; } public int? BlogId { get; set; } public Blog Blog { get; set; } }
然后我們開始遷移..
記得每次遷移,都需要創建一個遷移版本!
我們執行命令如下(注意,我們的版本已經改為了2):
Add-Migration BanBen2
成功創建遷移文件之后,我們更新數據庫.
Update-Database
成功信息如下:
然后我們進入數據庫看看效果:
我們發現Content的長度限制已經改為了50
2.刪除遷移
有的時候我們剛剛創建了一個遷移,還沒應用到數據庫,就發現自己需要變更實體.那我們就可以刪除這個沒有應用的遷移版本.
執行命令如下:(注意,這里是沒有應用過的遷移,可以刪除.如果應用過了.則會收到錯誤信息)
Remove-Migration
3.遷移回滾.
有些時候,我們需要回滾到之前的一個遷移版本.,比如我們部署的時候,開發版本和穩定版本肯定不一樣..
那么我們就會用到回滾命令.
執行如下:
Update-Database 這里填寫需要回滾的版本名
,比如我們執行如下:
Update-Database BanBen1
然后我們會發現,BanBen2中的長度限制,已經沒有了..
4.生成一個遷移SQL腳本
有的時候,我們的生產數據庫,是需要用腳本來創建庫的.所以我們也可以直接通過實體來生成SQL腳本.命令如下:
Script-Migration
就會生成對應的遷移SQL腳本.如下:
CREATE TABLE `__EFMigrationsHistory` ( `MigrationId` varchar(95) NOT NULL, `ProductVersion` varchar(32) NOT NULL, CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`) ); INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) VALUES ('20180316015722_BanBen1', '2.0.2-rtm-10011'); ALTER TABLE `Posts` MODIFY COLUMN `Content` varchar(50) NULL; ALTER TABLE `Posts` ALTER COLUMN `Content` DROP DEFAULT; INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) VALUES ('20180316022508_BanBen2', '2.0.2-rtm-10011');
當然,這個腳本可以自定義需要遷移的版本號.文件名,需要生成遷移腳本的上下文(多個上下文的情況).
5.遷移腳本的幫助說明.
我們可以通過命令來獲取幫助說明
Get-Help about_EntityFrameworkCore
get-help Add-Migration -full
get-help Script-Migration -full
.