Kingmaker
Kingmaker

Reputation: 509

EF Core 5 separate migrations into class library

I try to separate EF Core migrations into a separate class library. I have an API project which references the class library with migrations.

I added

to both projects.

In the migrations class library, I have an extension method where I register DbContext into services:

public static IServiceCollection AddTMS(this IServiceCollection services, IConfiguration configuration)
{
    var tmsConfiguration = configuration.GetSection("TMS");

    services.AddDbContext<TMSDbContext>(opt =>
        {
            opt.UseSqlServer(tmsConfiguration.GetSection("ConnectionString").Value, sqlOpt =>
            {
                sqlOpt.MigrationsHistoryTable("_TMSMigrationsHistory");
                sqlOpt.MigrationsAssembly(typeof(TMSDbContext).AssemblyQualifiedName);
            });
        });

    return services;
}

This extension method is then called in Startup.ConfigureServices method. When I try to add initial migration into class library project via

dotnet ef migrations add InitialMigration --project .\TMS.csproj --startup-project ..\API\API.csproj --output-dir ./Database/Migrations --context TMSDbContext --verbose

then creating migration fails with this error:

Using application service provider from Microsoft.Extensions.Hosting.
Found DbContext 'TMSDbContext'.
Finding DbContext classes in the project...
Found DbContext 'BOSDbContext'.
Found DbContext 'BOSCommonDbContext'.
Using context 'TMSDbContext'.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding design-time services referenced by assembly 'API'...
Finding design-time services referenced by assembly 'TMS'...
No referenced design-time services were found.
Finding IDesignTimeServices implementations in assembly 'API'...
No design-time services were found.

System.IO.FileLoadException: The given assembly name or codebase was invalid.

I know that if I implement IDesignTimeDbContextFactory<T> to create DbContext then it will work, but can it work without implementing this stupid interface?

Upvotes: 1

Views: 390

Answers (1)

Kingmaker
Kingmaker

Reputation: 509

By the time I have found the solution. The right implmentation for AddTMS method looks like this:

public static IServiceCollection AddTMS(this IServiceCollection services, IConfiguration configuration)
{
    var tmsConfiguration = configuration.GetSection("TMS");

    services.AddDbContext<TMSDbContext>(opt =>
    {
        opt.UseSqlServer(tmsConfiguration.GetSection("ConnectionString").Value, sqlOpt =>
        {
         sqlOpt.MigrationsHistoryTable("_TMSMigrationsHistory");
         sqlOpt.MigrationsAssembly(typeof(TMSDbContext).Assembly.FullName);
        });
    });

    return services;
}

See the difference in

sqlOpt.MigrationsAssembly(typeof(TMSDbContext).AssemblyQualifiedName);

vs.

sqlOpt.MigrationsAssembly(typeof(TMSDbContext).Assembly.FullName);

Upvotes: 1

Related Questions