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)
{
//
}
}
I could remove this and replace it with a different initializer (e.g.
CreateDatabaseIfNotExists
) but then theConfiguration
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.