Building an Entity Framework 7 MVC Web App using Visual Studio 2013 – Part 4

In this blog we remove the last migration that we added/applied and replace it with another one.  We also do some more work with the Code First Fluent API.

If you have been following this blog series you know we have been using .NET Framework 4.5.1 to build our app since the packages provided for EF7 support it. We are also using Visual Studio 2013 as it provides a very stable development environment. You will also note that we are mainly focusing on EF7 and haven’t done too much with MVC except to display the animals in our database on a web page. Eventually we will take what we have learned and apply it within ASP.NET 5. Using EF7 in .NET 4.5 projects has the added advantage of easy porting to the optimized cloud stack using CoreCLR. We will now pick up from the last post which was Part 3.

Being able to remove the last migration you applied is huge. Let’s say you just applied a migration to your testing environment, tests are now failing, and they would like you to remove it. If we tried to run Remove-Migration as a first step the command would rightly complain that we have applied the last migration to our database. We first need to unapply the last migration from the database. The way we do that is by reapplying the migration immediately prior to the one we want to remove.

Remember that the database is tracking these migrations for us in the __MigrationHistory table.
migrationmetadataLet’s reapply the ModifyZooAnimalSighting migration. In Package Manager Console enter the following.
Apply-Migration -Migration ModifyZooAnimalSighting -Project SightingsWebApp -Verbose
You will see this message at the end of the run
Reverting migration '201502121757538_ZPRBList_1'
Note with latest night build I do not see this message.
If we now check our database again we will see the migration has been dropped from our database.

reapplymigration

Now if we run Remove-Migration as shown below, the last migration is removed from our project like it never happened. Note in latest nightly build the file is not dropped in the Migrations folder. Manually delete this file from Migrations folder if it has not been removed.

removemigration

Let’s take this opportunity to clean up our Fluent API use. In our ZooSightingDemoDb class which is derived from DbContext, the last Fluent API code update we made  in the OnConfiguring method looked like this.

            modelBuilder.Entity<ZPRBAnimalClassificationList>()
                .ForRelational()
                .Table("AnimalClassification", "ZPRB");

            modelBuilder.Entity<ZPRBAnimalClassificationList>()
                .Key(z => z.Identifier);

            modelBuilder.Entity<ZPRBAnimalClassificationList>()
                .Property(z => z.Identifier)
                .ForSqlServer()
                .Column("Id");

            modelBuilder.Entity<ZPRBAnimalClassificationList>()
                .Property(z => z.Identifier)
                .GenerateValueOnAdd();

We can shorten that to:

            modelBuilder.Entity<ZPRBAnimalClassificationList>(b =>
            {
                b.Key(z => z.Identifier);
                b.ForSqlServer().Table("AnimalClassification", "ZPRB");
                b.Property(z => z.Identifier)
                    .GenerateValueOnAdd()
                    .ForSqlServer().Column("Id");
            });

That is a lot less code and we should test everything out after we apply the migration again.
We had other requirements to address with our new ZPRBAnimalClassificationList class if you remember.

"You have been told that the database type for decimal needs to be a decimal(8, 1) and that the RowVersion property will serve as a concurrency token to support optimistic concurrency. Also the Guid (globally unique identifier) needs to be the primary key. The Name property is required in the database and has a maximum size of 500 characters. We also need the database to generate the GUIDs for us on an INSERT. You are allowed to change the names of the table or columns in the database that represent this model class."

Here is the code to address the rest of the model configuration. Place this below the previous code in the OnModelCreating method in class ZooSightingDemoDb.

 

            modelBuilder.Entity<ZPRBAnimalClassificationList>(b =>
            {
                b.Property(z => z.MilesToNearestZPRBOffice)
                    .ForSqlServer()
                    .ColumnType("decimal(8, 1)")
                    .Column("ZPRBDistance");
                b.Property(z => z.RowVersion)
                    .ConcurrencyToken();
                b.Property(z => z.Name)
                    .Required()
                    .MaxLength(500);
            });

Go ahead and build the project making sure there are no errors.
Let’s run a new migration again
Add-Migration -Verbose -Project SightingsWebApp -Name ZPRBList_1
Then
Apply-Migration -Migration ZPRBList_1 -Project SightingsWebApp -Verbose

Looking at the database some of the configuration we are requesting is not happening such as the Name column is not limited to 500 characters. Waiting for this to improve.
Never forget we are working with beta4 code!

This is the sql that got sent to the database.

 

CREATE TABLE [ZPRBAnimalClassificationList] (
    [Identifier] uniqueidentifier NOT NULL,
    [IsIndigenous] bit,
    [MeetsAllZPRBPoliciesSetForth] bit,
    [MilesToNearestZPRBOffice] decimal(18, 2),
    [Name] nvarchar(max) NOT NULL,
    [RowVersion] rowversion,
    CONSTRAINT [PK_ZPRBAnimalClassificationList] PRIMARY KEY NONCLUSTERED ([Identifier])
);