public static IWebHost MigrateDbContext <TContext>(this IWebHost webHost, Action <TContext, IServiceProvider> seeder) where TContext : DbContext { var watch = new Stopwatch(); watch.Start(); var underK8S = webHost.IsInKubernetes(); using (var scope = webHost.Services.CreateScope()) { var services = scope.ServiceProvider; var logger = services.GetRequiredService <ILogger <TContext> >(); var context = services.GetRequiredService <TContext>(); try { logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); if (underK8S) { InvokeSeeder(seeder, context, services); } else { var retry = Policy.Handle <SqlException>() .WaitAndRetry(new[] { TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(8), }); //if the sql server container is not created on run docker compose this //migration can't fail for network related exception. The retry options for DbContext only //apply to transient exceptions // Note that this is NOT applied when running some orchestrator (let the orchestrator to recreate the failing service) retry.Execute(() => InvokeSeeder(seeder, context, services)); watch.Stop(); SystemEvents.Database.MigrateComplete(new DatabaseMigrateEventArgs { DbContext = context, ContextName = context.GetType().Name, ElapsedMilliseconds = watch.ElapsedMilliseconds }); } logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); } catch (Exception ex) { logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); if (underK8S) { throw; // Rethrow under k8s because we rely on k8s to re-run the pod } } } watch.Stop(); return(webHost); }
public static IWebHost MigrateDbContext <TContext>(this IWebHost webHost, Action <TContext, IServiceProvider> seeder) where TContext : DbContext { var underK8s = webHost.IsInKubernetes(); using var scope = webHost.Services.CreateScope(); TryMigrateAndSeed(scope, underK8s, seeder); return(webHost); }
public static IWebHost MigrateDbContext <TContext>(this IWebHost webHost, Action <TContext, IServiceProvider> seeder) where TContext : DbContext { var underK8S = webHost.IsInKubernetes(); using (var scope = webHost.Services.CreateScope()) { var services = scope.ServiceProvider; var logger = services.GetRequiredService <ILogger <TContext> >(); var context = services.GetService <TContext>(); try { logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); if (underK8S) { InvokeSeeder(seeder, context, services); } else { const int retries = 10; var policy = Policy.Handle <DbUpdateException>() .WaitAndRetry( retryCount: retries, sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), onRetry: (exception, timeSpan, retry, ctx) => { logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); }); //if the sql server container is not created on run docker compose this //migration can't fail for network related exception. The retry options for DbContext only //apply to transient exceptions // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) policy.Execute(() => InvokeSeeder(seeder, context, services)); } logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); } catch (Exception ex) { logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); if (underK8S) { throw; // Rethrow under k8s because we rely on k8s to re-run the pod } } } return(webHost); }
public static IWebHost MigrateDbContext <TContext>(this IWebHost webHost, Action <TContext, IServiceProvider> seeder) where TContext : DbContext { var underK8S = webHost.IsInKubernetes(); using var scope = webHost.Services.CreateScope(); var serviceProvider = scope.ServiceProvider; var logger = serviceProvider.GetRequiredService <ILogger <TContext> >(); var context = serviceProvider.GetService <TContext>(); try { logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); if (underK8S) { InvokeSeeder(seeder, context, serviceProvider); } else { var retries = 10; var retry = Policy.Handle <SqlException>() .WaitAndRetry(retryCount: retries, sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), onRetry: (exception, timeSpan, r, ctx) => { logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, r, retries); }); retry.Execute(() => InvokeSeeder(seeder, context, serviceProvider)); } logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); } catch (Exception ex) { logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); if (underK8S) { throw; } } return(webHost); }
public static IWebHost MigrateDbContext <TContext>(this IWebHost host, Action <TContext, IServiceProvider> seeder) where TContext : DbContext { var underK8s = host.IsInKubernetes(); using (var scope = host.Services.CreateScope()) { var services = scope.ServiceProvider; var logger = services.GetRequiredService <ILogger <TContext> >(); var context = services.GetService <TContext>(); try { logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); if (underK8s) { InvokeSeeder(seeder, context, services); } else { var retry = Policy.Handle <SqlException>() .WaitAndRetry(new TimeSpan[] { TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(8), }); retry.Execute(() => InvokeSeeder(seeder, context, services)); } logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); } catch (Exception ex) { logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); if (underK8s) { throw; } } } return(host); }
public static IWebHost MigrateDbContext <TContext>(this IWebHost webHost, Action <TContext, IServiceProvider> seeder) where TContext : DbContext { var underK8s = webHost.IsInKubernetes(); using (var scope = webHost.Services.CreateScope()) { var services = scope.ServiceProvider; var logger = services.GetRequiredService <ILogger <TContext> >(); var context = services.GetService <TContext>(); try { logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); if (underK8s) { InvokeSeeder(seeder, context, services, logger); } else { var retry = Policy.Handle <SqlException>() .WaitAndRetry(new TimeSpan[] { TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(8) }); //if the sql server container is not created on run docker compose this //migration can't fail for network related exception. The retry options for DbContext only //apply to transient exceptions // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) retry.Execute(() => InvokeSeeder(seeder, context, services, logger)); } logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); } catch (Exception ex) { logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); } } return(webHost); }