DEV Community

Dzenan
Dzenan

Posted on • Updated on

How to add Entity Framework Core migrations to own assembly

What we want to do is to store migrations in its own project/assembly for easier maintenance and to keep migration specific code out of the production binaries. We also do not want our startup project to depend on migration specific libraries.

For this example I assume we already have a project in place
that could look something like this

MyApp.Web.Api <-- ASP.Net Project
MyApp.Application <-- Class Library
MyApp.Domain <-- Class Library
MyApp.Infrastructure <-- Class Library (contains DBContext)

Create new migrations class library

We start by creating new class library to hold our migrations
called MyApp.Infrastructure.Migrations

dotnet new classlib -n MyApp.Persistence.Migrations
Enter fullscreen mode Exit fullscreen mode

We add reference to Microsoft.EntityFrameworkCore and Microsoft.EntityFrameworkCore.Design. The later is needed for the tooling to be able to detect and generate migration scripts

From MyApp.Infrastructure.Migrations folder

dotnet add package Microsoft.EntityFrameworkCore --version 5.0.1
dotnet add package Microsoft.EntityFrameworkCore.Design --version 5.0.1
Enter fullscreen mode Exit fullscreen mode

Add reference to project containing DBContext

The entity framework migrations tool need to find our DBContext that is located in different project so we need to reference our MyApp.Infrastructure project

From MyApp.Infrastructure.Migrations folder

dotnet add reference ../MyApp.Infrastructure/MyApp.Infrastructure.csproj
Enter fullscreen mode Exit fullscreen mode

Implement IDesignTimeDbContextFactory

To avoid need to use the startup project we need to implement IDesignTimeDbContextFactory so that migration tools can find the appropriate DBContext file. So we crate a new file called ApplicationDbContextFactory.cs with code below

ApplicationDbContextFactory.cs

using System;
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using MyApp.Infrastructure;

namespace MyApp.Infrastructure.Migrations
{
    public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
    {
        public ApplicationDbContext CreateDbContext(string[] args)
        {
            var configuration = new ConfigurationBuilder()
                 .SetBasePath(Directory.GetCurrentDirectory())
                 .AddJsonFile("appsettings.json", true)
                 .AddEnvironmentVariables()
                 .Build();

            var builder = new DbContextOptionsBuilder();

            var connectionString = configuration
                        .GetConnectionString("DefaultConnection");

            builder.UseSqlServer(connectionString,
                        x => x.MigrationsAssembly(typeof(ApplicationDbContextFactory).Assembly.FullName));



            return new ApplicationDbContext(builder.Options);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

We are letting the tool initialize our DBContext directly from our migrations library so we need to provide the connection string.
We do that by creating appsettings.json file inside our migrations class library

appsettings.json

{ 

    "ConnectionStrings": {
        "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=myapp;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
}
Enter fullscreen mode Exit fullscreen mode

Add migrations

Now run the migrations add to create our migrations folder structure inside our new project

From MyApp.Infrastructure.Migrations folder

dotnet ef migrations add InitialCreate
Enter fullscreen mode Exit fullscreen mode

Top comments (0)