public static class DatabaseMigrationExtensions { /// <summary> /// Chave para acesso à flag indicando que a database deve ser migrada ao inicializar. /// </summary> public const string MigrateDatabaseFlagKey = "MigrateOnStartup"; /// <summary> /// Garante que a base de dados está atualizada. /// </summary> /// <param name="host"></param> /// <returns></returns> public static IHost EnsureMigrated(this IHost host) { using var scope = host.Services.CreateScope(); var services = scope.ServiceProvider; var logger = services.GetRequiredService<ILogger<MyContext>>(); var context = services.GetRequiredService<MyContext>(); var configuration = services.GetRequiredService<IConfiguration>(); var migrateFlag = configuration.GetValue<bool>(MigrateDatabaseFlagKey); if (migrateFlag) { var retryPolicy = Policy .Handle<InvalidOperationException>() .WaitAndRetry(10, (attemptNum) => { logger.LogWarning("Erro ao migrar a database. Foram realizadas {0} tentativas", attemptNum); return TimeSpan.FromSeconds(5 * attemptNum); }); var result = retryPolicy.ExecuteAndCapture(() => { CheckAndApplyMigrationsInternal(logger, context); }); if (result.Outcome == OutcomeType.Failure) { logger.LogCritical(result.FinalException, "Não foi possível migrar a base de dados, a API não será executada"); } } return host; } /// <summary> /// Verifica e aplica as migrations pendentes. /// </summary> /// <param name="logger"></param> /// <param name="context"></param> private static void CheckAndApplyMigrationsInternal(ILogger<MyContext> logger, MyContext context) { var pendingMigrations = context.Database.GetPendingMigrations(); if (pendingMigrations.Any()) { logger.LogInformation($"Existem {pendingMigrations.Count()} migrations pendentes: {string.Join(", ", pendingMigrations)}"); context.Database.Migrate(); } } }