【问题标题】:Seamless EF Migrations from Staging > Production with Schema Change从暂存的无缝 EF 迁移 > 具有架构更改的生产
【发布时间】:2016-12-04 19:24:30
【问题描述】:

我有一个简单的网络应用程序。它由一个带有暂存槽和生产槽的 Azure Web 应用程序组成。当不需要考虑数据库迁移时,我可以通过以下方式轻松实现无缝更新:

  1. 将应用部署到暂存
  2. 交换分段 生产槽

当我需要处理数据库迁移时,这会变得更加棘手。现在我要做的是:

  1. 将应用部署到暂存
  2. 部署就绪后,将 update-database 运行到 Prod(无暂存数据库)
  3. 交换分段 生产槽

这意味着我仍然有效地有停机时间,因为 2 + 3 不会同时发生,这意味着在几秒钟内,由于“数据库架构已更改”,我的用户将体验到不完美的行为。

这里最简单的解决方案是什么?我在想我可能也必须启动一个暂存数据库,但是我不得不担心复制和连接字符串管理,这会增加一些开销。

【问题讨论】:

    标签: entity-framework azure ef-code-first azure-sql-database


    【解决方案1】:

    在将解决方案迁移到持续交付模型时,我们也面临同样的困境,并且希望避免停机。

    您需要配置您的 EF 以在开发环境中运行 Code-First 并在生产环境中运行 Database-First

    这使得您可以将更改推送到三个阶段:

    第一阶段。数据库迁移

    在此阶段,您将使用 EF 的 migrate.exe 实用程序(或简单地事先编写脚本)针对实时数据库运行最新迁移。应用迁移后,您的网站在生产中仍然可以正常运行,因为没有发生任何事情(因为它被配置为数据库优先)。

    重要的一点是你需要确保你在这个阶段的迁移是additive的,因为它会改变一个比方说的表或列这将导致现场网站崩溃。它可能看起来很吓人,但是如果您的项目足够成熟,您很快就会意识到对架构的大多数更改要么完全是附加的,要么可以分为两个阶段。 (见第 3 阶段)

    第 2 阶段。更新生产网站

    在这个阶段进行正常的Staging --> Production网站部署。

    第 3 阶段。数据库迁移(第 2 部分)

    在极少数情况下,例如重命名数据库表或列,您需要考虑将其分为两个步骤:

    • 添加新列(在第 1 部分中完成)
    • 删除旧列并迁移数据(在第 2 部分中完成)。

    附录

    EF Database-First 仅在生产中

    在您的Startup.csGlobal.asax.cs

    #if DEBUG
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppDatabase, Migrations.Migrations.Configuration>());
    #else
        Database.SetInitializer(new RequireDatabaseToBeUpToDate<AppDatabase, Migrations.Migrations.Configuration>());
    #endif
    

    这正是它在锡上所说的:

    • 在本地:将其数据库迁移到最新迁移。
    • 生产中:确保数据库迁移不领先它正在使用的模型程序集。 -- 这是一项安全措施,确保即使我们在数据库之前意外部署了网络,它也能阻止网站启动。

    public class RequireDatabaseToBeUpToDate<TContext, TMigrationsConfiguration> : IDatabaseInitializer<TContext>
        where TContext : DbContext 
        where TMigrationsConfiguration : DbMigrationsConfiguration, new()
    {
        public void InitializeDatabase(TContext context)
        {
            var migrator = new DbMigrator(new TMigrationsConfiguration());
            var migrations = migrator.GetPendingMigrations().ToList();
            if (migrations.Any())
            {
                var message = "There are pending migrations that must be applied (via a script or using migrate.exe) before the application is started.\r\n" +
                    $"Pending migrations:\r\n{string.Join("\r\n", migrations)}";
                throw new MigrationsPendingException(message);
            }
        }
    }
    

    针对实时数据库运行迁移

    $migrate = "<path>\migrate.exe"
    $migrateConfig = "<path>\migrate.exe.config"
    $connectionString = <your-live-connection-string>
    & $migrate <your-project-migration-assembly> /startupConfigurationFile=$migrateConfig <your-migration-configuration-type-name> /connectionString=$connectionString /connectionProviderName=System.Data.SqlClient /verbose
    

    【讨论】:

    • 第 3 阶段仍然会给您带来停机时间。由于站点交换和迁移不是同时进行的。根据我的经验,这种情况并不罕见,因为表格往往会经常变化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 2014-08-10
    • 2017-03-15
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多