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

目录

背景

更改表名称和架构

更改列名称

添加具有默认值的列

添加必填列

关于代码示例

引用


背景

实体框架核心通过在名为__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

引用

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值