自定义EF Core迁移历史记录表

2023-05-16

目录

背景

更改表名称和架构

更改列名称

添加具有默认值的列

添加必填列

关于代码示例

引用


  • 下载源代码 - 13.9 KB

背景

实体框架核心通过在名为__EFMigrationsHistory和架构dbo的表中添加日志来跟踪应用的迁移。迁移表包含两列MigrationIdProductVersion。在这里,我们将探索一些自定义此表的选项。

  • 更改迁移表名称和架构
  • 更改迁移表的列名
  • 在迁移表中添加默认值列
  • 在迁移表中添加必填列

更改表名称和架构

我们将对迁移表使用自定义表名称__Migrations和模式名称track。模式名称是可选的,如果未指定,则默认为dbo

public class AppDb : DbContext
{
    public DbSet<Process> Process { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var config = new ConfigurationBuilder()
            .AddJsonFile(Path.Combine(AppContext.BaseDirectory, "appsettings.json"), 
             optional: false, reloadOnChange: true)
            .Build();
        optionsBuilder
            .UseSqlServer(config.GetConnectionString("DatabaseConnection"), 
                d => { d.MigrationsHistoryTable("__Migrations", "track"); });
    }
}

更改列名称

要更改列名,我们将用自定义配置类HistoryRepository替换现有的/默认服务类型IHistoryRepository

public class AppDb : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var config = new ConfigurationBuilder()
            .AddJsonFile(Path.Combine(AppContext.BaseDirectory, "appsettings.json"), 
                         optional: false, reloadOnChange: true)
            .Build();
        optionsBuilder
            .UseSqlServer(config.GetConnectionString("DatabaseConnection")})
            .ReplaceService<IHistoryRepository, HistoryRepository>();
    }
}

在这里,我们将表列名称从:

  • MigrationIdId
  • ProductVersionVersion

internal class HistoryRepository : SqlServerHistoryRepository
{
    public HistoryRepository(HistoryRepositoryDependencies dependencies) : 
                             base(dependencies)
    {
    }
    protected override void ConfigureTable(EntityTypeBuilder<HistoryRow> history)
    {
        base.ConfigureTable(history);
        history.Property(h => h.MigrationId).HasColumnName("Id");
        history.Property(h => h.ProductVersion).HasColumnName("Version");
    }
}

ConfigureTable(EntityTypeBuilder<HistoryRow> history)方法中,此部分实际上看起来更小,就像使用Fluent API的实体映射一样。我们应该能够更改其他内容,例如表名、模式名称、数据类型等。我还没有尝试过,但从逻辑上讲,这应该有效。

添加具有默认值的列

向项目添加空迁移Init。请务必确保这是第一次迁移,并在将任何表或任何其他对象添加到DbContext类之前添加。最初,UpDown方法将为空。

Add-Migration Init

Up

将新列AppliedAtUtc添加到迁移表[track].[__Migrations]中,并为该列创建约束DF__Migrations_AppliedAtUtc,以将当前UTC日期时间设置为默认值。

Down

删除我们在up部分和列本身中添加的约束。

public partial class Init : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql("ALTER TABLE [track].[__Migrations] 
                              ADD AppliedAtUtc DATETIME NULL;");
        migrationBuilder.Sql("ALTER TABLE [track].[__Migrations] 
                              ADD CONSTRAINT DF__Migrations_AppliedAtUtc 
                              DEFAULT GETUTCDATE() FOR [AppliedAtUtc];");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropCheckConstraint("DF__Migrations_AppliedAtUtc", 
                                             "__Migrations", "track");
        migrationBuilder.DropColumn("AppliedAtUtc", "__Migrations", "track");
    }
}

等效的SQL

/*changes*/
ALTER TABLE [track].[__Migrations] ADD CreatedON DATETIME NULL;
ALTER TABLE [track].[__Migrations] _
      ADD CONSTRAINT DF__Migrations_CreatedON DEFAULT GETUTCDATE() FOR [CreatedON];
/*rollback*/
ALTER TABLE [track].[__Migrations] DROP CONSTRAINT DF__Migrations_CreatedON;
ALTER TABLE [track].[__Migrations] DROP COLUMN CreatedON;

添加必填列

在这里,我们将向迁移表添加一个必需列ProjectName

public class AppDb : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var config = new ConfigurationBuilder()
            .AddJsonFile(Path.Combine(AppContext.BaseDirectory, 
            "appsettings.json"), optional: false, reloadOnChange: true)
            .Build();
        optionsBuilder
            .UseSqlServer(config.GetConnectionString("DatabaseConnection")})
            .ReplaceService<IHistoryRepository, HistoryRepository>();
    }
}

ConfigureTable(EntityTypeBuilder<HistoryRow> history)里面,我们根据需要添加一个新列。在GetInsertScript(HistoryRow row)方法中,我们正在为迁移表创建自定义insert语句。

public class ContextConstants
{
    public static string ProjectName = "Console";
}

internal class HistoryRepository : SqlServerHistoryRepository
{
    public const string CustomColumnName = "ProjectName";
    public HistoryRepository(HistoryRepositoryDependencies dependencies) : 
                             base(dependencies)
    {
    }
    protected override void ConfigureTable(EntityTypeBuilder<HistoryRow> history)
    {
        base.ConfigureTable(history);
        history.Property<string>(CustomColumnName).HasMaxLength(300).IsRequired();
    }
    public override string GetInsertScript(HistoryRow row)
    {
        var stringTypeMapping = 
            Dependencies.TypeMappingSource.GetMapping(typeof(string));
        return new StringBuilder()
            .Append("INSERT INTO ")
            .Append(SqlGenerationHelper.DelimitIdentifier(TableName, TableSchema))
            .Append("(")
            .Append(SqlGenerationHelper.DelimitIdentifier(MigrationIdColumnName))
            .Append(", ")
            .Append(SqlGenerationHelper.DelimitIdentifier(ProductVersionColumnName))
            .Append(", ")
            .Append(SqlGenerationHelper.DelimitIdentifier(CustomColumnName))
            .Append(") ")
            .Append("VALUES (")
            .Append(stringTypeMapping.GenerateSqlLiteral(row.MigrationId))
            .Append(", ")
            .Append(stringTypeMapping.GenerateSqlLiteral(row.ProductVersion))
            .Append(", ")
            .Append(stringTypeMapping.GenerateSqlLiteral(ContextConstants.ProjectName))
            .Append(")")
            .AppendLine(SqlGenerationHelper.StatementTerminator)
            .ToString();
    }
}

关于代码示例

  • Visual Studio 2022 Solution
  • EF Core 6(也使用EF Core 5进行测试)
  • 检查Db.Custom项目代码,AppDb.cs。为了进行测试,我们需要将此项目设置为启动项目。

appsettings.json中,我们将找到目标数据库连接:

{
  "ConnectionStrings": {
    "DatabaseConnection": "Data Source=.\\SQLEXPRESS;Initial Catalog=Cup;
                           Integrated Security=True"
  }
}

命令:

Add-Migration Init
Update-Database
Script-Migration

Drop-Database 
Remove-Migration Init

db

引用

  • Custom Migrations History Table - EF Core | Microsoft Learn
  • How to Customize Migration History Table with Entity Framework Core - Stack Overflow

https://www.codeproject.com/Articles/5338891/Customize-Entity-Framework-Core-Migration-History

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义EF Core迁移历史记录表 的相关文章

随机推荐

  • 天干地支计算

    年的干支 方法一 xff1a 首先要能记住十大天干和十二地支 xff0c 十天干 xff1a 甲 乙 丙 丁 戊 己 庚 辛 壬 癸 xff1b 十二地支 xff1a 子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥 xff1b 天干地支纪年
  • 程序员们,AI来了,机会来了,危机也来了

    程序员们 xff0c AI来了 xff0c 机会来了 xff0c 危机也来了 1 人工智能真的来了 纵观古今 xff0c 很少有计算机技术能有较长的发展寿命 xff0c 大部分昙花一现 xff0c 比如 xff1a 昔日的DOS windo
  • 统信UOS 20 1050 记录一次openssl升级失败的排查过程

    目录 不能找到openssl最新版本的原因 fedora有相关module的介绍 一些yum module 常用的命令 xff1a 查看yum module 都有哪些 启用禁用module 总结 xff1a 后记 xff1a 通过yum l
  • iOS之富文本

    之前做项目时遇到一个问题 xff1a 使用UITextView显示一段电影的简介 xff0c 由于字数比较多 xff0c 所以字体设置的很小 xff0c 行间距和段间距也很小 xff0c 一大段文字挤在一起看起来很别扭 xff0c 想要把行
  • JetBrains IntelliJ IDEA 2022.2 使用 Java 17 运行时

    JetBrains 发布 了 IntelliJ IDEA 2022 2 xff0c 支持 Java 17 和最新的语言和框架 xff0c 如 Scala Kotlin Spring 6 和 Spring Boot 3 这个新版本使用了 Je
  • Linux生产者消费者模型实现

    转载请注明出处 xff1a https blog csdn net mymottoissh article details 84181224 任何语言提及到多线程同步都离不开生产者 消费者模型 这也是针对许多现实问题建模用到的基础模型 这一
  • 使用CMD启动JAR后,出现定时器不执行问题

    SpringBoot项目中 使用了 64 Scheduled注解开启一个定时任务 在windows系统启动时 开始输出正常 当执行到输出控制台日志时 有时候会直接卡住线程不执行了 查了一圈发现是CMD的快速编辑引起的线程阻塞 解决办法 1
  • Flink开发中遇到的问题及解法

    1 当Source是Kafka的时候 xff0c 如何设置Source Operator的并发度 xff1f 如果没有指定 xff0c Source Operator的个数与集群中的TaskManager的个数相等 如果手动设置 xff0c
  • vue初学者代码格式报错

    报错内容 xff1a Do not use built in or reserved HTML elements as component id header
  • Ubuntu 设置su密码

    在使用su命令获取超级权限的时候提示输入密码 xff0c 在安装ubuntu的时候只设置了用户密码 xff0c 没记得有其他密码 这里需要给root用户重新设置密码 xff1a sudo passwd 然后输入密码即可
  • Spark MLlib学习(二)——分类和回归

    MLlib支持多种分类方法 xff0c 如二分类 多分类和回归分析等 问题类型 支持的方法 二分类 线性SVM 逻辑回归 xff0c 决策树 xff0c 随机森林 xff0c GBDT xff0c 朴素贝叶斯 多分类 决策树 xff0c 随
  • 关于onNewIntent你应该知道的

    一 API描述如下 大概意思是当Activity被设以singleTop模式启动 xff0c 当需要再次响应此Activity启动需求时 xff0c 会复用栈顶的已有Activity xff0c 还会调用onNewIntent方法 并且 x
  • 程序猿的情话

    世界上最遥远的距离 xff0c 是我在if里你在else里 xff0c 似乎一直相伴又永远分离 xff1b 世界上最痴心的等待 xff0c 是我当case你是switch xff0c 或许永远都选不上自己 xff1b 世界上最真情的相依 x
  • SpringBoot JPA实践之EntityManage查询返回自定义DTO

    在很多时候我更喜欢随意组合查询出来返回一个DTO对象的实现 xff0c JPA提供的多数查询均以返回Entity居多 xff0c 它提供的EntityManager对象可以实现将SQL语句查询的结果转换为自定义DTO对象 xff08 这与
  • 经典编程书籍(C++, 网络, Windows, Linux)【转载】

    书单中列举的都是相关领域的经典书籍 xff0c 必读之作 此书单的编辑参考了很多网站 xff0c 包括一些名家的推荐 xff0c 例如侯捷 xff0c 孟岩 xff0c 荣耀 xff0c 潘爱民等等 xff0c 在此也向这些前辈表示感谢 1
  • SpringBoot微服务框架概述

    SpringBoot微服务框架 2 Spring Boot 微服务框架的特点3 Spring Boot 应用场景4 SpringBoot的第一个应用5 Springboot引导类的main方法有什么作用 xff1f 6 SpringBoot
  • 使用Spring的注解方式实现AOP

    Spring对AOP的实现提供了很好的支持 下面我们就使用Spring的注解来完成AOP做一个例子 首先 xff0c 为了使用Spring的AOP注解功能 xff0c 必须导入如下几个包 aspectjrt jar aspectjweave
  • 如何正确有效的学习一门计算机语言?

    在这个互联网高速发展的社会 xff0c 越来越多的人喜欢上了IT行业 xff0c 认为计算机行业是一个高科技的 高薪的行业 的确如此 xff0c 但是系统的学习一门计算机语言 xff0c 并且把它用运用到真正的开发中去还真不是一件简单的事情
  • (二)为AI和机器学习创建Docker容器

    目录 介绍 基本镜像 创建Dockerfile 构建镜像 运行容器 总结 下载源文件 154 4 KB 介绍 Docker 等容器技术显着简化了软件的依赖管理和可移植性 在本系列文章中 xff0c 我们探讨了 Docker 在机器学习 ML
  • 自定义EF Core迁移历史记录表

    目录 背景 更改表名称和架构 更改列名称 添加具有默认值的列 添加必填列 关于代码示例 引用 下载源代码 13 9 KB 背景 实体框架核心通过在名为 EFMigrationsHistory 和架构 dbo 的表中添加日志来跟踪应用的迁移