Running Entity Framework Core Migrations with Optimizely CMS 12
Martin Soderlund Ek
Posted on October 9, 2024
So you've added your new Entity Framework DbContext
to the Startup ConfigureServices
method, everything works fine locally when you start your web application. Your database table(s) are created, migrations work both ways. Now you only need this working for other environments.
Enter the good old initialization engine in Optimizely.
What we want to do is:
- Scan all classes inheriting from DbContext.
- Go through your Entity Framework contexts and check if they have pending migrations.
- Apply any pending migrations.
Here's the full solution:
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using Microsoft.EntityFrameworkCore;
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class EntityFrameworkMigrationInitialization : IConfigurableModule
{
public void ConfigureContainer(ServiceConfigurationContext context)
{
context.Services.AddTransient<EFCoreMigrationService>();
}
public void Initialize(InitializationEngine context)
{
var migrationService = context.Locate.Advanced.GetInstance<EFCoreMigrationService>();
migrationService.CheckAndApplyMigrations();
}
public void Uninitialize(InitializationEngine context)
{
}
}
public class EFCoreMigrationService
{
private readonly ILogger<EntityFrameworkMigrationInitialization> _logger;
private readonly IServiceProvider _serviceProvider;
public EFCoreMigrationService(IServiceProvider serviceProvider, ILogger<EntityFrameworkMigrationInitialization> logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
public void CheckAndApplyMigrations()
{
using (var scope = _serviceProvider.CreateScope())
{
// Get all DbContext types in the application
var dbContextTypes = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic && !a.ReflectionOnly)
.SelectMany(a => a.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(DbContext)));
foreach (var contextType in dbContextTypes)
{
var context = scope.ServiceProvider.GetService(contextType) as DbContext;
if (context != null)
{
if (context.Database.GetPendingMigrations().Any())
{
_logger.LogError($"Applying EF migrations for {contextType.Name}");
context.Database.Migrate();
}
}
}
}
}
}
💖 💪 🙅 🚩
Martin Soderlund Ek
Posted on October 9, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.