上篇文章: EFCore生產環境數據庫升級方案 中我們聊了如何將EFCore遷移(實體模型變更)應用到生產環境的方案,在上次的演示中,我們是將所有遷移存放到了定義DbContext的類庫項目中去,在這邊文章中我來介紹下如何將遷移單獨存放到一個類庫項目中去,以便管理EF生成的遷移文件。
這篇文章中,我們繼續使用 EFCore生產環境數據庫升級方案 中的例子項目進行改造,來實現將所有EF遷移文件單獨提取到類庫項目中去,本文和 EFCore生產環境數據庫升級方案 是同一個系列的文章,如果你還沒有閱讀前一篇文章,強烈建議先閱讀前文。
一、新建類庫項目,將EF遷移文件及遷移快照文件移動到新的類庫項目中
新建名稱為 EFMigrations.DataMigrations 的類庫項目
這里需要注意的是:如果還沒有生成任何遷移文件,則請先至少生成一個,再將新生成的遷移文件復制到新建的類庫項目EFMigrations.DataMigrations 中去。
二、類庫項目添加對包含DbContext上下文類的引用。
添加EFMigrations.Models類庫項目的引用到EFMigrations.DataMigrations,如下:
三、將默認的遷移程序集指定為新建的類庫項目。
將EFMigrations.Models 中的所有的EF遷移文件及遷移生成的SQL腳本文件移動到EFMigrations.DataMigrations項目中去。
移動完畢后,EFMigrations.Models中僅包含EF DbContext 上下文類,以及實體模型,如下圖所示:
四、告訴啟動項目遷移程序集是哪個
啟動項目指的是告訴 EF命令行遷移工具從哪個項目開始啟動,然后執行遷移文件的生成,這里我們的啟動項目是EFMigrations.Web 項目,修改Startup.cs文件中的ConfigureService方法如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(builder=> {
builder.UseSqlServer(Configuration["ConnectionStrings:ConnectionStr"],optionsBuilder=> {
//這里告訴EFcore 命令行遷移工具,等下生成的遷移文件放到EFMigrations.DataMigrations 項目中去。
optionsBuilder.MigrationsAssembly("EFMigrations.DataMigrations");
});
});
services.AddControllersWithViews();
}
添加EFMigrations.DataMigrations的引用到EFMigrations.Web,然后重新生成下EFMigrations.Web項目,否則等下生成遷移會失敗,因為不添加引用等下EFMigrations.Web項目啟動后開始生成遷移的時候會找不到EFMigrations.DataMigrations.dll
五、測試新添加的遷移是否正常生成到了新建的類庫項目中去。
我們新建一個實體模型OrderInfo,並將其添加到DbContext 上下文中去。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace EFMigrations.Models
{
public class OrderInfo
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int OrderId { get; set; }
public int ProductId { get; set; }
public double Price { get; set; }
public int BuyCount { get; set; }
public int UserId { get; set; }
}
}
修改DbContext上下文類,增加OrderInfo實體映射。
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;
namespace EFMigrations.Models
{
public class MyDbContext : DbContext
{
/// <summary>
/// 這里一定要聲明一個接收DbContextOptions參數的構造函數,否則無法正常添加遷移。
/// </summary>
/// <param name="options"></param>
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{
}
public DbSet<UserInfo> UserInfos { get; set; }
public DbSet<OrderInfo> OrderInfos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
}
}
}
打開程序包管理控制台,輸入以下命令:
cd ./EFMigrations.DataMigrations 將當前目錄定位到遷移程序所在項目的根目錄下,免得下面這個步驟生成遷移文件的時候還要額外用-p 參數指定遷移程序集的項目路徑。
dotnet ef migrations add OrderInfo_CreateTable -s ../EFMigrations.Web
遷移生成成功后如下:
將新生成的遷移轉換成SQL,在程序包管理控制台中輸入以下命令:
dotnet ef migrations script 20210830142733_UserInfo_AddColumns 20210902141104_OrderInfo_CreateTable -s ../EFMigrations.Web -o ./SqlScripts/OrderInfo_CreateTable.sql
以上命令的意思是將 20210830142733_UserInfo_AddColumns遷移(不包含)的下一個遷移開始,截止到 20210902141104_OrderInfo_CreateTable(包含) 之間的所有遷移轉換成SQL腳本進行生成,生成成功后,SQL腳本如下:
六、將SQL腳本升級到數據庫
- 首先需要將生成的SQL腳本設置成在生成項目的時候嵌入到程序集:鼠標右擊 OrderInfo_CreateTable.sql ,選擇屬性->生成操作->嵌入的資源
- 然后將EFMigrations.Models 類中的 ApplicationBuilderExtensions 類移動到EFMigrations.DataMigrations項目中去,之所以這么做是方便dbup-sql 類庫找.sql腳本時直接從當前程序集中查找
- 重啟網站,看下是否新SQL腳本是否成功被升級到了數據庫
這里需要注意的是,由於在上一篇文章中我已經將前面兩個SQL 腳本升級到了數據庫中,並且很有意思的事情是dbup-sqlserver記錄已升級腳本的名稱時帶上了程序集明明空間,因此這里直接運行會升級失敗,我們必須手動先將數據庫中的已升級腳本記錄的前綴名稱更新為EFMigartions.DataMigrations開頭方能再次升級成功。
我們將EFMigrations.Models替換成EFMigrations.DataMigrations后再重新升級,如下圖顯示,表示升級成功了