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 theFepazoConfiguration
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();
// <...>
}
Make sure the MigrateDatabaseToLatestVersion will be using the correct context that the application is using. This is done by using the parameter useSuppliedContext.
After this change, my MVC application did update my database.
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.
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.
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>?