MigrateDatabaseToLatestVersion not executed

2019-03-18 10:40发布

I can't figure out why my latest migration is not getting executed automatically on application startup (or at least on first access of the database context). I used to run update-database manually in development, but I want to test whether it will upgrade automatically on my hosted test environment.

In Application_Start():

Database.SetInitializer<FepazoContext>(
    new MigrateDatabaseToLatestVersion<FepazoContext, FepazoConfiguration>())

In FepazoConfiguration:

internal sealed class FepazoConfiguration : 
    DbMigrationsConfiguration<Fepazo.Models.FepazoContext>
{
    public FepazoConfiguration()
    {
        AutomaticMigrationsEnabled = true;
    }
}

I even added this to the constructor of FepazoContext:

public FepazoContext() : base("DefaultConnection")
{
    Database.Initialize(false);
}

Some extra information:

  • The migration was automatically created through add-migration and looks ok.
  • When I query the __MigrationHistory table, I can see that the migration is not yet 'recorded' as executed.
  • I verified that the initializer or the AutomaticMigrationsEnabled setting isn't overridden in Web.config file.
  • Breakpoints in FepazoContext constructor and the FepazoConfiguration are getting hit.

Am I forgetting something ? Can I dig deeper to find out where it goes wrong ?

Updates

Passing True to Database.Initialize to try and force the migration also has no effect. Database.CompatibleWithModel(true) returns false - so the system detects there is a difference, however it does not execute the pending migration!

public FepazoContext() : base("DefaultConnection")
{
    if (!Database.CompatibleWithModel(true))
    {
        // This is executed (each time the code enters)
        Database.Initialize(true);
    }
}

Workaround

As a workaround, I call DbMigrator.Update() explicitly right after setting the initializer. That does the trick, although I'd still like to know why it doesn't work automatically...

protected void Application_Start()
{
    // <...>
    Database.SetInitializer<FepazoContext>(
        new MigrateDatabaseToLatestVersion<FepazoContext, FepazoConfiguration>());
    var dbMigrator = new DbMigrator(new FepazoConfiguration());
    dbMigrator.Update();
    // <...>
}

4条回答
劳资没心,怎么记你
2楼-- · 2019-03-18 11:01

Make sure the MigrateDatabaseToLatestVersion will be using the correct context that the application is using. This is done by using the parameter useSuppliedContext.

Database.SetInitializer<FepazoContext>(
    new MigrateDatabaseToLatestVersion<FepazoContext, FepazoConfiguration>(useSuppliedContext: true));

After this change, my MVC application did update my database.

查看更多
淡お忘
3楼-- · 2019-03-18 11:03

In the above code snippet you are calling the Database.Initialize() method immediately after creating a context instance. In this case, the database will be created immediately after calling the Initialize() method instead of waiting until the context is used for the first time.

The Initialize() method takes a Boolean parameter that controls whether the initialization process should re-run if it has already run for the application.

Specifying false will skip the initialization process if it has already executed. A value of true will initialize the database again even if it was already initialized.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-03-18 11:10

According to another answer on here the initializer doesn't run until there is some interaction with the database. The answer explains how to force the initializer to run immediately.

查看更多
【Aperson】
5楼-- · 2019-03-18 11:15

I had this issue. My problem turned out to be that I had a MigrationsContextFactory that was being used to provide the connection string. When the database initialization was occurring the migration context factory was being called. This MigrationsContextFactory was getting a connection string to a different database and was ensuring that was up to date.

I removed the MigrationsContextFactory and passed true to MigrateDatabaseToLatestVersion<,> Migrator to tell it to use the current context. See this question top voted answer How do I inject a connection string into an instance of IDbContextFactory<T>?

查看更多
登录 后发表回答