EF6 How do I retain a custom sql generator while disabling automatic migrations

c# ef-code-first entity-framework-6

Question

We use entity framework 6 in our application, along with a Custom Sql Server Migration Generator that handles some edge cases when generating migrations.

We use add-migration to add a new migration to the system, and then when the application is deployed, our deployment tool runs migrate.exe to update the target database with any pending migrations.

However, we've discovered that the migrations are being applied automatically ANYWAY to any database we happen to connect to while running the application. This is highly undesirable behaviour for our application. We want it to not work if there is a mismatch between the application model and the database it is trying to connect to.

I believe this is because we are using the following:

// Supply configuration reference to Initializer
Database.SetInitializer(new MigrateDatabaseToLatestVersion<OurContext, OurDb.Migrations.Configuration>(useSuppliedContext: true));

I could remove this and replace it with a different initializer (e.g. CreateDatabaseIfNotExists) but then the Configuration would not be used, because the constructor does not have a parameter for configuration:

// No opportunity to supply configuration?
Database.SetInitializer<OurDb>(new CreateDatabaseIfNotExists<OurDb>());

So my question is, how do I retain the custom sql generator while disabling the automatic migrations?

Here's part of our Configuration.cs class:

internal sealed class Configuration : DbMigrationsConfiguration<OurDb>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        AutomaticMigrationDataLossAllowed = false;
        SetSqlGenerator("System.Data.SqlClient", new CustomSqlServerMigrationSqlGenerator());
    }

    protected override void Seed(OurDb context)
    {
        //
    }
}
1
4
7/29/2019 12:07:53 PM

Popular Answer

I could remove this and replace it with a different initializer (e.g. CreateDatabaseIfNotExists) but then the Configuration would not be used, because the constructor does not have a parameter for configuration

It's true that you have to use different initializer. But the conclusion is wrong. The truth is that

your configuration (along with the custom MigrationSqlGenerator) will be used with any predefined initializer.

They don't have parameter for configuration because simply they don't need it. Although not publicly exposed, EF6 database context has access to its associated migration configuration. Otherwise public Database class methods like Create or CreateIfNotExists won't work correctly.

If you are wondering why MigrateDatabaseToLatestVersion initializer needs the configuration parameter, the answer is that MigrateDatabaseToLatestVersion is an exception.

All other out-of-the-box initializers have equivalent public Database class methods (or combination of methods). That's not true for MigrateDatabaseToLatestVersion - it uses directly DbMigrator class and has an option to ignore the passed context instance (not sure what's the use case for that), which requires passing DbMigrationsConfiguration to the DbMigrator constructor - source code.

3
8/6/2019 9:24:33 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow