自定义迁移历史记录表

注意

仅限 EF6 及更高版本 - 此页面中讨论的功能、API 等已引入实体框架 6。 如果使用的是早期版本,则部分或全部信息不适用。

注意

本文假设你了解如何在基本场景中使用 Code First 迁移。 如果你不知道,则需要先阅读 Code First 迁移,再继续。

什么是迁移历史记录表?

迁移历史记录表是一个表,Code First 迁移使用该表来存储有关向数据库的迁移的详细信息。 默认情况下,该表在数据库中名为 __MigrationHistory,是在首次进行向数据库的迁移时创建的。 在 Entity Framework 5 中,如果应用程序使用 Microsoft Sql Server 数据库,则该表是系统表。 但在 Entity Framework 6 中,这一点有所变化,迁移历史记录表不再标记为系统表。

为什么自定义迁移历史记录表?

迁移历史记录表应仅供 Code First 迁移使用,手动对其进行更改可能会导致迁移中断。 但有时默认配置不适用,需自定义该表,例如:

  • 需更改列的名称和/或 facet,以启用第三方迁移提供程序
  • 你要更改表的名称
  • 你需要使用 __MigrationHistory 表的非默认架构
  • 你需要为指定版本的上下文存储额外的数据,因此需向表中添加额外的列

预防信息

更改迁移历史记录表功能非常强大,但需谨慎,不要过度使用。 EF 运行时当前不检查自定义的迁移历史记录表是否与运行时兼容。 如果不兼容,应用程序可能会在运行时时中断,或以不可预测的方式运行。 如果为每个数据库使用多个上下文,则这一点更加重要,在这种情况下,多个上下文可以使用同一迁移历史记录表来存储有关迁移的信息。

如何自定义迁移历史记录表?

开始前,需要知道的是,仅在进行第一次迁移前可以自定义迁移历史记录表。 接下来,了解代码相关的内容。

首先,需创建派生自 System.Data.Entity.Migrations.History.HistoryContext 类的类。 HistoryContext 类派生自 DbContext 类,因此配置迁移历史记录表与使用 fluent API 配置 EF 模型非常相似。 只需重写 OnModelCreating 方法并使用 fluent API 来配置表。

注意

通常,配置 EF 模型时,无需从重写的 OnModelCreating 方法调用 base.OnModelCreating(),因为 DbContext.OnModelCreating() 具有空主体。 配置迁移历史记录表时并非如此。 在这种情况下,OnModelCreating() 重写时首先要实际调用 base.OnModelCreating()。 这将以默认方式配置迁移历史记录表,然后你可以在重写的方法中对默认方式进行修改。

假设你要重命名迁移历史记录表并将其放入名为“管理员”的自定义架构。 并且 DBA 希望你将 MigrationId 列重命名为 Migration_ID。  则你可以通过创建以下派生自 HistoryContext 的类来实现此目的:

    using System.Data.Common;
    using System.Data.Entity;
    using System.Data.Entity.Migrations.History;

    namespace CustomizableMigrationsHistoryTableSample
    {
        public class MyHistoryContext : HistoryContext
        {
            public MyHistoryContext(DbConnection dbConnection, string defaultSchema)
                : base(dbConnection, defaultSchema)
            {
            }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Entity<HistoryRow>().ToTable(tableName: "MigrationHistory", schemaName: "admin");
                modelBuilder.Entity<HistoryRow>().Property(p => p.MigrationId).HasColumnName("Migration_ID");
            }
        }
    }

自定义 HistoryContext 准备就绪后,需通过基于代码的配置将其注册,以让 EF 知道它:

    using System.Data.Entity;

    namespace CustomizableMigrationsHistoryTableSample
    {
        public class ModelConfiguration : DbConfiguration
        {
            public ModelConfiguration()
            {
                this.SetHistoryContext("System.Data.SqlClient",
                    (connection, defaultSchema) => new MyHistoryContext(connection, defaultSchema));
            }
        }
    }

这很简单。 现在可以转到包管理器控制台、Enable-Migrations、Add-Migration,最后转到 Update-Database。 完成这些后,会向数据库添加根据 HistoryContext 派生类中指定的详细信息配置的迁移历史记录表。

Migrations History Table