Search code examples
c#entity-frameworkdatabase-migrationentity-framework-migrations

Converting the column type in No Magic Migration


I have an entity which contains a property of type TimeSpan. We have decided to changed the property from TimeSpan to Int (minutes). My Idea now to migrate this changes as following:

Retrieving each entry from the old column(TimeSpan) and convert it to minute (Int) and add it in the new created column.

Where/what is the best approach to do that? Shall I do it in the Seed method?! I think, this is not possible because Seed is called after the migration is done.

The second approach in Up() method. Is this a good idea? Copy/Convert the column data into another column in the Up method.

public partial class V30 : DbMigration
{
     public override void Up()
     {

      AddColumn("dbo.Plexes", "ISingleIsValidTimeInMinutes", c => c.Int(nullable: false));

      // I NEED HERE TO TRANSFER THE DATA FROM ISingleIsValidTime TO ISingleIsValidTimeInMinutes ?!!!
      TransformISingleIsValidTimeToInt();

      DropColumn("dbo.Plexes", "ISingleIsValidTime");
     }
....
}

private void TransformISingleIsValidTimeToInt()
{
  // HERE CONVERTING LOGIC I NEED THE EXISITNG DATA FROM DBCONTEXT!!
}

 public class NoMagicDatabaseConfiguration : DbMigrationsConfiguration<ApplicationDbContext>
 {

   public NoMagicDatabaseConfiguration()
   {
    this.AutomaticMigrationsEnabled = false;
    this.AutomaticMigrationDataLossAllowed = false;
   }

   protected override void Seed(ApplicationDbContext context)
   {
    base.Seed(context);
   }
 }

Solution

  • The easiest (and probably quickest) way would be to run a SQL statement with the Sql method, something along the lines of :

    public override void Up()
    {
      AddColumn("dbo.Plexes", "ISingleIsValidTimeInMinutes", c => c.Int(nullable: false));
      Sql("UPDATE Plexes SET ISingleIsValidTimeInMinutes = -DATEDIFF(MINUTE, ISingleIsValidTime, 0)");
      DropColumn("dbo.Plexes", "ISingleIsValidTime");
    }
    

    Alternatively, if you want to solve this problem using EF alone, you could instantiate your context during the up migration between adding and removing the columns and do the work there, but if you have a lot of rows, it could take a while