Efcore: More than one DbContext was found. Specify which one to use

Created on 27 Apr 2018  路  3Comments  路  Source: dotnet/efcore

dotnet ef migrations script -i -o scripts.sql

I can't find a way to generate one migration script for a project with multiple DbContexts

It kinda becomes an issue when you are trying to do it with VSTS CI/CD if you want to see the migration script first before you deploy it.

However, what I don't understand is when I use
dotnet ef database update -c ApplicationDbContext

It actually generates every DbContext with every migration.

but dotnet ef migrations script -i -o scripts.sql -c ApplicationDbContext only generates scripts for tables related to ApplicationDbContext.

closed-question

Most helpful comment

Sounds like dbContext.Database.Migrate() is getting called (possibly from a Startup or a constructor) on every context when you call dotnet ef database update.

You can probably do some fancy shell scripting to get a script for every context:

dotnet ef dbcontext list | foreach {
    dotnet ef migrations script -c $_ >> scripts.sql
}

All 3 comments

Sounds like dbContext.Database.Migrate() is getting called (possibly from a Startup or a constructor) on every context when you call dotnet ef database update.

You can probably do some fancy shell scripting to get a script for every context:

dotnet ef dbcontext list | foreach {
    dotnet ef migrations script -c $_ >> scripts.sql
}

Well, I thought about that. However, if I do that kinda script, how to make sure the migration history is the same?

For example:

00000000000000_CreateIdentitySchema
20180302222420_custom_tbl_name
20180309232758_InitialIdentityServerPersistedGrantDbMigration
20180309232832_InitialIdentityServerConfigurationDbMigration

The first 2 are from ApplicationDbContext. The 3rd and 4th are 2 other different DbContext.

What if I have another migration history for ApplicationDbContext in the end? The sequence for a new database will be different.

It might not be a problem because they are all different DBContexts.

However, I feel like there should be a way to generate a script just like calling dotnet ef database update

(I do have dbContext.Database.Migrate() in startup for ApplicationDbContext and have

var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddTestUsers(Config.GetUsers())
    // this adds the config data from DB (clients, resources)
    .AddConfigurationStore(options =>
    {
        options.ConfigureDbContext = builder =>
            builder.UseSqlServer(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));
    })
    // this adds the operational data from DB (codes, tokens, consents)
    .AddOperationalStore(options =>
    {
        options.ConfigureDbContext = builder =>
            builder.UseSqlServer(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));

        // this enables automatic token cleanup. this is optional.
        options.EnableTokenCleanup = true;
        options.TokenCleanupInterval = 30;
    });

)

It might not be a problem because they are all different DBContexts.

Correct. Migrations for different contexts shouldn't overlap (see also #2725). Their IDs are also sufficiently unique to never clash.

It shouldn't be a problem, but if it is, you can configure each context to have its own history table:

protected override void OnConfiguring(DbContextOptionsBuilder options)
    => options.UseSqlServer(
        connectionString,
        x => x.MigrationsHistoryTable("__MyMigrationsHistory"));
Was this page helpful?
0 / 5 - 0 ratings