Skip to content

Commit 3ee0c49

Browse files
committed
separated migrate and seed
1 parent eb2af4f commit 3ee0c49

File tree

1 file changed

+59
-40
lines changed

1 file changed

+59
-40
lines changed

src/Extensions/IWebHostExtensions.cs

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Data.SqlClient;
33
using Microsoft.AspNetCore.Hosting;
44
using Microsoft.EntityFrameworkCore;
5-
using Microsoft.Extensions.Configuration;
65
using Microsoft.Extensions.DependencyInjection;
76
using Microsoft.Extensions.Logging;
87
using Polly;
@@ -11,46 +10,77 @@ namespace Extensions
1110
{
1211
public static class IWebHostExtensions
1312
{
14-
public static bool IsInKubernetes(this IWebHost webHost)
13+
public static IWebHost MigrateDbContext<TContext>(this IWebHost webHost) where TContext : DbContext
1514
{
16-
var cfg = webHost.Services.GetService<IConfiguration>();
17-
return CheckIfK8s(cfg);
15+
using var scope = webHost.Services.CreateScope();
16+
17+
TryMigrate<TContext>(scope);
18+
19+
return webHost;
1820
}
1921

20-
private static bool CheckIfK8s(IConfiguration cfg)
22+
public static Microsoft.Extensions.Hosting.IHost MigrateDbContext<TContext>(this Microsoft.Extensions.Hosting.IHost host) where TContext : DbContext
2123
{
22-
var orchestratorType = cfg.GetValue<string>("OrchestratorType");
23-
return orchestratorType?.ToUpper() == "K8S";
24+
using var scope = host.Services.CreateScope();
25+
26+
TryMigrate<TContext>(scope);
27+
28+
return host;
2429
}
2530

26-
public static IWebHost MigrateDbContext<TContext>(this IWebHost webHost, Action<TContext, IServiceProvider> seeder) where TContext : DbContext
31+
public static IWebHost MigrateDbContext<TContext>(this IWebHost webHost, Action<TContext, IServiceProvider> seeder = default) where TContext : DbContext
2732
{
28-
var underK8s = webHost.IsInKubernetes();
29-
3033
using var scope = webHost.Services.CreateScope();
3134

32-
TryMigrateAndSeed(scope, underK8s, seeder);
35+
TryMigrateAndSeed(scope, seeder);
3336

3437
return webHost;
3538
}
3639

37-
public static bool IsInKubernetes(this Microsoft.Extensions.Hosting.IHost host)
40+
public static Microsoft.Extensions.Hosting.IHost MigrateDbContext<TContext>(this Microsoft.Extensions.Hosting.IHost host, Action<TContext, IServiceProvider> seeder = default) where TContext : DbContext
3841
{
39-
var cfg = host.Services.GetService<IConfiguration>();
40-
return CheckIfK8s(cfg);
42+
using var scope = host.Services.CreateScope();
43+
44+
TryMigrateAndSeed(scope, seeder);
45+
46+
return host;
4147
}
4248

43-
public static Microsoft.Extensions.Hosting.IHost MigrateDbContext<TContext>(this Microsoft.Extensions.Hosting.IHost webHost, Action<TContext, IServiceProvider> seeder) where TContext : DbContext
49+
private static void TryMigrateAndSeed<TContext>(IServiceScope scope, Action<TContext, IServiceProvider> seeder) where TContext : DbContext
4450
{
45-
var underK8s = webHost.IsInKubernetes();
51+
var services = scope.ServiceProvider;
4652

47-
using var scope = webHost.Services.CreateScope();
48-
TryMigrateAndSeed(scope, underK8s, seeder);
53+
var logger = services.GetRequiredService<ILogger<TContext>>();
4954

50-
return webHost;
55+
var context = services.GetService<TContext>();
56+
57+
try
58+
{
59+
logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name);
60+
61+
62+
var retry = Policy.Handle<SqlException>()
63+
.WaitAndRetry(new TimeSpan[]
64+
{
65+
TimeSpan.FromSeconds(3),
66+
TimeSpan.FromSeconds(5),
67+
TimeSpan.FromSeconds(8),
68+
});
69+
70+
//if the sql server container is not created on run docker compose this
71+
//migration can't fail for network related exception. The retry options for DbContext only
72+
//apply to transient exceptions
73+
retry.Execute(() => InvokeSeeder(seeder, context, services));
74+
75+
logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name);
76+
}
77+
catch (Exception ex)
78+
{
79+
logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name);
80+
}
5181
}
5282

53-
private static void TryMigrateAndSeed<TContext>(IServiceScope scope, bool underK8s, Action<TContext, IServiceProvider> seeder) where TContext : DbContext
83+
private static void TryMigrate<TContext>(IServiceScope scope) where TContext : DbContext
5484
{
5585
var services = scope.ServiceProvider;
5686

@@ -62,36 +92,25 @@ private static void TryMigrateAndSeed<TContext>(IServiceScope scope, bool underK
6292
{
6393
logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name);
6494

65-
if (underK8s)
66-
{
67-
InvokeSeeder(seeder, context, services);
68-
}
69-
else
70-
{
71-
var retry = Policy.Handle<SqlException>()
72-
.WaitAndRetry(new TimeSpan[]
73-
{
95+
96+
var retry = Policy.Handle<SqlException>()
97+
.WaitAndRetry(new TimeSpan[]
98+
{
7499
TimeSpan.FromSeconds(3),
75100
TimeSpan.FromSeconds(5),
76101
TimeSpan.FromSeconds(8),
77-
});
102+
});
78103

79-
//if the sql server container is not created on run docker compose this
80-
//migration can't fail for network related exception. The retry options for DbContext only
81-
//apply to transient exceptions
82-
// Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service)
83-
retry.Execute(() => InvokeSeeder(seeder, context, services));
84-
}
104+
//if the sql server container is not created on run docker compose this
105+
//migration can't fail for network related exception. The retry options for DbContext only
106+
//apply to transient exceptions
107+
retry.Execute(() => context.Database.Migrate());
85108

86109
logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name);
87110
}
88111
catch (Exception ex)
89112
{
90113
logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name);
91-
if (underK8s)
92-
{
93-
throw; // Rethrow under k8s because we rely on k8s to re-run the pod
94-
}
95114
}
96115
}
97116

0 commit comments

Comments
 (0)