如何将EFCore迁移分离到单独类库项目?

     上篇文章: EFCore生产环境数据库升级方案 中我们聊了如何将EFCore迁移(实体模型变更)应用到生产环境的方案,在上次的演示中,我们是将所有迁移存放到了定义DbContext的类库项目中去,在这边文章中我来介绍下如何将迁移单独存放到一个类库项目中去,以便管理EF生成的迁移文件。

这篇文章中,我们继续使用 EFCore生产环境数据库升级方案 中的例子项目进行改造,来实现将所有EF迁移文件单独提取到类库项目中去,本文和 EFCore生产环境数据库升级方案 是同一个系列的文章,如果你还没有阅读前一篇文章,强烈建议先阅读前文。

一、新建类库项目,将EF迁移文件及迁移快照文件移动到新的类库项目中

新建名称为 EFMigrations.DataMigrations 的类库项目

这里需要注意的是:如果还没有生成任何迁移文件,则请先至少生成一个,再将新生成的迁移文件复制到新建的类库项目EFMigrations.DataMigrations 中去。

二、类库项目添加对包含DbContext上下文类的引用。

添加EFMigrations.Models类库项目的引用到EFMigrations.DataMigrations,如下:

如何将EFCore迁移分离到单独类库项目?

 

三、将默认的迁移程序集指定为新建的类库项目。

将EFMigrations.Models 中的所有的EF迁移文件及迁移生成的SQL脚本文件移动到EFMigrations.DataMigrations项目中去。

移动完毕后,EFMigrations.Models中仅包含EF DbContext 上下文类,以及实体模型,如下图所示:

如何将EFCore迁移分离到单独类库项目?

四、告诉启动项目迁移程序集是哪个

启动项目指的是告诉 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

如何将EFCore迁移分离到单独类库项目?

 

五、测试新添加的迁移是否正常生成到了新建的类库项目中去。

我们新建一个实体模型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 

迁移生成成功后如下:

如何将EFCore迁移分离到单独类库项目?

将新生成的迁移转换成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脚本如下:

如何将EFCore迁移分离到单独类库项目?

 

六、将SQL脚本升级到数据库

  • 首先需要将生成的SQL脚本设置成在生成项目的时候嵌入到程序集:鼠标右击 OrderInfo_CreateTable.sql ,选择属性->生成操作->嵌入的资源
  • 然后将EFMigrations.Models 类中的 ApplicationBuilderExtensions 类移动到EFMigrations.DataMigrations项目中去,之所以这么做是方便dbup-sql 类库找.sql脚本时直接从当前程序集中查找

        如何将EFCore迁移分离到单独类库项目?

  • 重启网站,看下是否新SQL脚本是否成功被升级到了数据库

这里需要注意的是,由于在上一篇文章中我已经将前面两个SQL 脚本升级到了数据库中,并且很有意思的事情是dbup-sqlserver记录已升级脚本的名称时带上了程序集明明空间,因此这里直接运行会升级失败,我们必须手动先将数据库中的已升级脚本记录的前缀名称更新为EFMigartions.DataMigrations开头方能再次升级成功。

如何将EFCore迁移分离到单独类库项目?

我们将EFMigrations.Models替换成EFMigrations.DataMigrations后再重新升级,如下图显示,表示升级成功了

如何将EFCore迁移分离到单独类库项目?

如何将EFCore迁移分离到单独类库项目?

上一篇:partition by和group by对比


下一篇:ES高级(23) 文档分析