예제 #1
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }