Using Code First Migrations

In this recipe we will use Code First code Migrations to evolve our model and update the database. You might be asking yourself why this is so important. Isn't this just another way of doing something we already knew how to do?

Not so! It solves a very important problem in a simple and efficient way. Haven't we all at some time had the problem of deploying software and keeping the database up-to-date? Well, this solves this exact problem. And in a very easy and simple way, I must add.

How? Keep reading.

Getting ready

In order to use this recipe, you should have Visual Studio 2012 installed. It would be good to have implemented the previous recipe and worked on the resulting solution.

How to do it...

Using this recipe we will implement Code First Migrations and show how to evolve our model and revert it to a previous version.

First, open Visual Studio 2012 and open the previous project. We recommend copying it to a new folder so if anything goes wrong (you all know Murphy is always present) we can start a new one.

Change the project name to EFCodeFirstMigrations.

We will start by enabling migrations. To do this, we will open the Package Manager Console option and type the Enable-Migrations command into it, pressing Return to execute it. We will observe that a Migrations folder has been created in the project with two source files, one for the initial creation of the database and the other for the configuration (configuration.cs).

We will open the configuration.cs file and change the AutomaticMigrationsEnabled property's value to true using the following line of code:

AutomaticMigrationsEnabled = true

Note that we could have enabled Automatic Migrations with this command:

Enable-Migrations – EnableAutomaticMigrations

Let's add a minor change to our BookModel class to see how this works out. We will add a Boolean property named IsOnSale as shown in the following code line:

public boolIsOnSale {get; set;}

Apply the pending changes from our code to the database with the command Update-Database that we will type into and execute with the Package Manager Console. If we want more details on what is happening, we can also execute this command with the –Verbose flag as shown in the following code line:

Update-Database –Verbose

It would be good to validate that our database has been properly generated, so we should open our Server Explorer panel and refresh it to reflect the changes.

Next, we will comment the added property and execute the Update-Database command again. It will not be executed because it would result in data loss.

We will uncomment the IsOnSale property and add a BookRating integer property to the BookModel class.

For medium to advanced scenarios for which we want more control over what happens, we have Code Migrations. We will enable it by going to our configuration.cs file and setting the AutomaticMigrationsEnabled property to false.

Then we will go to our Package Manager Console and execute the Add-Migration command, followed by the name we want to give to this code migration. We will use the name BookRating as it describes very well what this migration will do.

Now a new file has appeared in our Migrations folder, named BookRating.cs, prefixed with a timestamp that will help us with the ordering. If we open it, we will clearly see and understand how it works:

public partial class BookRating : DbMigration
{
    public override void Up()
    {
    AddColumn("dbo.BookModels", "BookRating", c =>c.Int(nullable: false));
    }

    public override void Down()
    {
    DropColumn("dbo.BookModels", "BookRating");
    }
}

There we can see the Up and Down methods that will be invoked when needed. We can modify them to do what we want. For example, we will rate the books with a rating of five by default. We will modify the AddColumn function with the following code:

AddColumn("dbo.BookModels", "BookRating",c =>c.Int(nullable:false, defaultValue:5));

The only thing left now is to update the database with the Update-Database command. Go on and execute it.

To validate that everything has gone as expected, we should open the Server Explorer panel, navigate to our database, and finally, right-click on our table, selecting the Show Table Data option. We can appreciate that the BookRating column has been added and also that its value has been set to 5 as shown in the following screenshot:

How to do it...

Now we are going to go back to the previous version. To do this, we will use the Update-Database command together with the –TargetMigration flag. We will execute the following code on the Package Manager Console window:

Update-Database -TargetMigration:"InitialCreate"

This will not execute properly as it will produce a loss of data. We must add the –Force flag to execute it without problems. Excecute the code previously mentioned, once again, but using the –Force flag:

Update-Database -TargetMigration:"InitialCreate" -Force

We can again update the database to the latest state with the Update-Database -TargetMigration:"BookRating" command. We don't have any reason to use the -Force flag since there will be no data loss in this case.

How it works...

We enabled Code First Migrations with the Enable-Migrations command and manually changed the mode to Automatic Migrations, showing its behavior with a simple property change.

With Automatic Migrations, we can execute the Update-Database command, and all is done for us, without any need to handle versions or anything else. We saw that this comes with the drawback of not being able to move to a previous version.

Continuing, we activated Code Migrations and generated a migration with the Add-Migration command, which, as we saw, we can use to move up and down within the different versions, and finally, we customized a bit of migration to provide a default value.

Next, we saw how to move back and forward in time to a specific migration in a very easy way and also used the -Force flag to enable proper downgrading in cases where the elimination of fields and/or tables is required. For this, the command is Update-Database –TargetMigration:"MigrationName", followed by the -Force flag, if needed.

There's more...

In addition, to what we have seen, we might want to perform some activity with the data to fit the new model, such as copying data from one table to another, prepopulating the new entity with a default value, and likewise. To do this, we can execute SQL at any point in our migration, as we can see in the following code:

Sql("UPDATE dbo.BookModels SET BookRating = 5");

Additionally we can automatically generate the update script with the –Script flag indicating the source and the destination migrations:

Update-Database -Script -SourceMigration:$InitialDatabase - TargetMigration:"BookRating"

Executing this would generate the necessary SQL script that we can then use to execute the migration directly on our SQL Server.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset