Bug #68889 EF 4.3.1 Code First Migration Tries to Migrate Already Migrated Database
Submitted: 8 Apr 2013 20:27 Modified: 11 Sep 2013 17:18
Reporter: Matt Woody Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S1 (Critical)
Version:Net Connector 6.6.5 OS:Any
Assigned to: Roberto Ezequiel Garcia Ballesteros CPU Architecture:Any
Tags: EntityFramework Migration CodeFirst

[8 Apr 2013 20:27] Matt Woody
Description:
Using MySQL 5.5.19, .Net Connector 6.6.5, VS2012, .Net 4.0 Client Profile, C# Visual Studio 2012 I am not able to use the automatic migration feature. I created a simple project and the database creation and migration initialzers work correctly using MSSQL, but the same code fails after switching to the MySQL .Net connector.

The MySQL database can be created automatically with the CreateDatabaseIfNotExists initializer and migrated one time with the MigrateDatabaseToLatestVersion intializer. But if the application is run again after the successful migration, an exception is thrown indicating that a duplicate column was created.

MySql.Data.MySqlClient.MySqlException was unhandled
  HResult=-2147467259
  Message=Duplicate column name 'NewColumn'
  Source=MySql.Data
  ErrorCode=-2147467259
  Number=1060
  StackTrace:
       at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
       at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
       at MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int64& insertedId)
       at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
       at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
       at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
       at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
       at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
       at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
       at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
       at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements)
       at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
       at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading)
       at System.Data.Entity.Migrations.DbMigrator.AutoMigrate(String migrationId, XDocument sourceModel, XDocument targetModel, Boolean downgrading)
       at System.Data.Entity.Migrations.Infrastructure.MigratorBase.AutoMigrate(String migrationId, XDocument sourceModel, XDocument targetModel, Boolean downgrading)
       at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
       at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
       at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
       at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update()
       at System.Data.Entity.MigrateDatabaseToLatestVersion`2.InitializeDatabase(TContext context)
       at System.Data.Entity.Database.<>c__DisplayClass2`1.<SetInitializerInternal>b__0(DbContext c)
       at System.Data.Entity.Internal.InternalContext.<>c__DisplayClass8.<PerformDatabaseInitialization>b__6()
       at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
       at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()
       at System.Data.Entity.Internal.LazyInternalContext.<InitializeDatabase>b__4(InternalContext c)
       at System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input)
       at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action)
       at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()
       at System.Data.Entity.Internal.InternalContext.Initialize()
       at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
       at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
       at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
       at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
       at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
       at System.Data.Entity.DbSet`1.Add(TEntity entity)
       at SimpleEF.Form1.button1_Click(Object sender, EventArgs e) in c:\Users\cmwoody\Documents\Visual Studio 2012\Projects\SimpleEF\SimpleEF\Form1.cs:line 27
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at SimpleEF.Program.Main() in c:\Users\cmwoody\Documents\Visual Studio 2012\Projects\SimpleEF\SimpleEF\Program.cs:line 24
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

How to repeat:
Steps to duplicate:

1. Create a project SimpleEF with Entity Framework 4.3.1 and MySql .Net 6.6.5
2. Create a context with one collection of class Item
namespace SimpleEF
{
    class MyDatabase: DbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //modelBuilder.Entity<Preferences>()
            //    .Property(d => d.StationName)
            //    .IsRequired()
            //    .HasColumnType("char");
        }
        public DbSet<MyItem> Items { get; set; }
    }
}
3. Create a class
namespace SimpleEF
{
    class MyItem
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string NewColumn { get; set; }
    }
}
4. Create a connection string in App.config
  <connectionStrings>
    <clear />
    <add name="MyDatabase" connectionString="server=localhost;userid=root;password=123;port=3306;database=asimpleef;pooling=false;" providerName="MySql.Data.MySqlClient" />
  </connectionStrings>
5. Set the initializer at startup
       static void Main()
        {
            //Database.SetInitializer<MyDatabase>(new CreateDatabaseIfNotExists<MyDatabase>());
            Database.SetInitializer<MyDatabase>(new MigrateDatabaseToLatestVersion<MyDatabase, Configuration>());
            
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
6. Create a form with a single button
        private void button1_Click(object sender, EventArgs e)
        {
            MyDatabase myDatabase = new MyDatabase();

            MyItem newItem = new MyItem();
            newItem.Name = "Name1";

            myDatabase.Items.Add(newItem);
            myDatabase.SaveChanges();

            MessageBox.Show("Done");
        }
7. Uncomment the initializer for creating the database and comment the migration one.
8. Delete the database if it exists, run the app and click the button. The database is created and a row is saved.
7. Comment the initializer for creating the database and uncomment the migration one.
9. Run the app and click the button. No error.
10. Modify the Item class by adding a field "NewColumn"
11. Run the app and click the button. The myitems table is updated.
12. Run the app again and the error occurs.

Suggested fix:
When running the app the second time no migration should be performed.
[11 Sep 2013 17:18] Daniel So
Added the following changelog entry for Connector/Net 6.6.6:

"When using Entity Framework 4.3.1 and Code First Migrations, databases were migrated more than once. This fix stops the problem by changing the CreatedOn column in the migration history table to use the 24-hour time format."