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
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
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
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);
}
}
}
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"
}
}
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
Top comments (0)