- [Voiceover] In this video we'll talk about
how to update the database schema that we
created in the last video so it can stay
in sync with our Model classes using
Entity Framework Code First Migrations.
Let's take a closer look at the CheckingAccounts table
that was just created in the Server Explorer.
Entity Framework did a nice job of setting up
this table given the information it had,
but there are few things I want to adjust now.
First, I don't need accountNumber
to be in VARCHAR(MAX).
I don't need to support different languages in
that column so I'd rather have a VARCHAR.
We talked about having those numbers
be between six and 10 digits,
so I'd really like to have it be VARCHAR(10).
Now I could just make these changes right here
or in SQL Server Management Studio,
but we want to create something that's going to be
easy to set up in or deploy to another environment.
A better place to make the changes is back
in the CheckingAccount class.
For accountNumber we see now
that the regular expression doesn't influence
the column type that's created.
It's not quite smart enough to use that.
I could uncomment this StringLength validator
and leave off the minimum value but I also
wanted to use VARCHAR instead of NVARCHAR
so in this case I'm going to explicitly set it
using the column attribute like so.
Use Ctrl+. to resolve this reference.
I'm going to give it TypeName is equal to "varchar".
Be careful not to put VARCHAR(10) there
because it won't understand that and
you'll get a somewhat cryptic error.
Now let's do Ctrl+F5 to build and start.
And because I was already logged in
I get a very useful error message that tells us
that things have changed since Entity Framework
magically created this database and unfortunately,
it can't magically update it for us,
but it suggests Code First Migrations
as a possible solution.
Go to Tools in the Main Menu,
NuGet Package Manager
and Package Manager Console.
Entity Framework is one of many NuGet packages
that we use in a MVC application and managing
Migrations is one thing we'll do
through the Package Manager console.
The First command that we want
to issue is Enable-Migrations.
This takes a Context type parameter
for which will supply our DB context name
ApplicationDbContext.
And now we see that it detected the existing
database and it also created an initial migration
in a new folder called Migrations.
You can think of this as a baseline
which it will use to determine what changes
will need to be made in the future
as we continue to change our models.
In the database you can see that we have a row
in the MigrationsHistory table corresponding
to this Migration which has been there all along.
Even though it didn't actually have to run a migration,
this is considered an implied migration at this point.
The other part of the highlighted message
in the Package Manager console mentioned
enabling automatic migrations,
and we'll do that momentarily since it makes
things a lot easier during these early stages
of development when your model classes
are frequently changing.
Let's see what it looks like
to do a manual migration first.
We want to push our changes to the accountNumber
property contraints to the database.
First we'll add a migration
with the Add-Migration command.
We'll give it a name like AccountNumberChanges.
It doesn't have to be all one word
but you'll need quotes if there are spaces.
Now we get a message about how the migration file
will be used and how we can overwrite it
if we need to make further changes
before applying it.
We can also just edit the file that it created directly.
The Up method is used to apply the changes,
and you can see "maxLength: 10",
unicode is false because we switched
from NVARCHAR to VARCHAR and the
Down method is for rolling them back.
We can also create a SQL script if necessary.
For example, if we needed to manually apply
these updates on a different server.
To do that we would use the Update-Database
command with the Script flag.
Most of this is just values for the
MigrationHistory table but at the top you can see
the statements for altering the accountNumber column.
If we just want to apply it to the database
immediately we'll use the Update-Database
command without the Script flag,
but we can give it the Verbose flag so we can
actually take a look at what it's doing.
We will talk about what it means by running
the Seed method later on.
It's also possible to rollback to a previous
state using the TargetMigration switch
with a name of a specific migration.
But for now let me just show you that
if we scroll up past this MigrationHistory data,
we can see that it actually did make the changes here.
We're going to go ahead and try registration now,
but before we do that remember that
we had hard-coded the account number
in the Register method.
Now that I know this is going to work
I'm going to go ahead and fix that really quickly.
I'm going to say that accountNumber should be
one, two, three, four, five, six plus
however many checking accounts we have
currently in the database,
and IntelliSense is a little confused
because we don't have an equal sign there.
However many accounts we have
currently in the database,
which I can get with db.CheckingAccounts.Count.
I'm going to convert that result to a string,
and then pad it with zeros on the left
for a checking account number of 10 digits.
And then use that instead of the
hard-coded value down here.
Obviously there are some problems with this.
One, two, three, four, five, six is an
arbitrary or a magic number which should be avoided
or at least stored in a config file.
If I ever deleted some accounts
I can end up duplicating an account number.
But for now this is good enough
for development purposes.
Let's go ahead and rebuild and try to register.
So that worked and let's look at the database.
Now we see our new checking account
with a unique account number
associated with a new user.
Let's make another change this time
with AutomaticMigrations enabled.
Open up Configuration.cs in the Migrations folder
and set AutomaticMigrationsEnabled to true.
Now let's make another small
change to CheckingAccount.
You may have noticed that the ApplicationUserID
on CheckingAccount was created as a nullable column.
If I don't want to allow nulls there
I should add a Required property or rather
a Required attribute to this property.
With AutomaticMigrations enabled to push
this change to the database all
I have to do is run Update-Database,
and we'll give it the Verbose flag again.
But now Entity Framework is a little worried
about potential data lost.
We're offered two ways to deal with this
and we'll use the -Force option to tell it
that we're not worried right now.
That gives you an idea of what's available to you
in terms of keeping your code synced with
your database schema with
Entity Framework Code First Migrations.
Remember that all of the code we've looked at
in this chapter is available to you in the
Exercise files in the final folder inside
the Chapter three folder.
Coming up you'll get some hands-on practice
with some of the concepts we've covered so far.