DEV Community

Martin Soderlund Ek
Martin Soderlund Ek

Posted on

Running Entity Framework Core Migrations with Optimizely CMS 12

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:

  1. Scan all classes inheriting from DbContext.
  2. Go through your Entity Framework contexts and check if they have pending migrations.
  3. 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();
                    }
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)