1
votes

In my ASP.NET MVC Web App backed by EF Code First using EF Migrations, I need better control of DB Updates, making them semi-automatic. The goal is to run them from code only (e.g. by running DbMigrator.Update()) but if not run, the application should still execute, ignoring possible alterations.

To accomplish this, I'm setting DbMigrationsConfiguration.AutomaticMigrationsEnabled to false, but during the first database access, I'm hitting the following Exception:

System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException: 'Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.'

The good part: I was able to omit the Exception by setting disableDatabaseInitialization="true" in Web.config as described at MSDN (I didn't find any other working way).

I'm running the following code on a custom trigger:

var config = new DbMigrationsConfiguration<MyContext>
{
    AutomaticMigrationsEnabled = false,
    AutomaticMigrationDataLossAllowed = false,
    MigrationsAssembly = Assembly.GetAssembly(typeof(InitialCreate)),
    MigrationsNamespace = typeof(InitialCreate).Namespace
};

var migrator = new DbMigrator(config);

migrator.Update(); // throws Exception

The Update call throws:

System.Data.SqlClient.SqlException: 'There is already an object named 'MyEntity' in the database.'

This might have something to do with the use of disableDatabaseInitialization. Also, the call to migrator.GetLocalMigrations() lists all the Migrations but migrator.GetDatabaseMigrations() lists none (empty), while there are already some Migrations applied.

Can you spot the error?

1

1 Answers

1
votes

After lots of trying, I was able to find out myself, the missing ContextKey Property caused the issues:

var config = new DbMigrationsConfiguration<MyContext>
{
    AutomaticMigrationsEnabled = false,
    AutomaticMigrationDataLossAllowed = false,
    MigrationsAssembly = Assembly.GetAssembly(typeof(InitialCreate)),
    MigrationsNamespace = typeof(InitialCreate).Namespace,

    ContextKey = nameof(MyContext) // Fixed the issue
};

Very interesting that I have to set all the fields myself. In the examples I found, people didn't need to setup anything.