Using Migrations with EF Core

Let Code Design Your Database

Migrations allow us to keep our database in sync with our code. We can write classes in C#, generate a migration, and then we'll have a database that's ready to store the data contained in instances of our classes.

Entity Framework is an Object Relational Mapper. That means it's able to map (convert) instances of objects into what's called "relational data". Relational databases are a very popular type of database right now. We'll be using SQL Server, which is a relational database that's created by Microsoft and pairs really well with C# (also from Microsoft).


What's a Migration?

Migrations are a class that implement two methods: Up and Down.

The Up method is responsible for transitioning the database from it's prior state, to the new state of the database.

The Down method is responsible for "undoing" the changes made by the Up method.


Example Migrations

Imagine if we had three migrations like this:

  1. CreateSongs
  2. AddLyricsToSong
  3. AddArtist

The Up method for the CreateSongs migration would be responsible for creating the table to store instances of our Song. The Down method for CreateSongs would delete the table that stores instances of our Song.

The Up method for the AddLyricsToSong would add a column to the Song table. The Down method would remove the column.

The Up method for the AddArtist migration would create a new table that stores Artists. The Down method would delete the new Artists table.

If that's the migrations we have, then we could go from an empty database to the current design by running the Up methods on each migration, in order.


Add-Migration

To migrate our database, the first thing we'll need to be able to do is create a new Migration.

Migrations are automatically generated for us, which is awesome. We don't need to write all the code that creates our database - we get it for free!

All we need to do is...

  • Create our Model class
  • Add our Model to a DbSet on our DbContext
  • Run the following command in the Package Manager Console:

    • Add-Migration MyNameInPascalCase.

When we run that command, EF compares our current DbContext and all of our models against how they looked the last time Add-Migration ran. It then figures out what's different between the two, and generates all the code to move the database forward so it matches our current DbContext and models.

It's a good practice to take a peek at the generated Migration file and make sure it's what you expected. If you added a model, you'd expect to see some code that looks like it's adding a table for that model. Removed a property? Something should be getting removed.


Remove-Migration

Migration isn't quite what you expected? No worries, you can use the Remove-Migration command to remove the last created migration. As long as you haven't updated the database yet, you'll be fine to remove it.

If you have updated the database, it's usually easier to just fix-forward. Update your DbContext and models as needed and add a new migration. Migrations are inexpensive.


Update-Database

So you've got that shiny new migration all ready to go, and now you need to apply those migrations to your database. We can do this using the Update-Database command.

When we run Update-Database it will apply any pending migrations to the database. If your database is already updated, it won't do anything. But if you either created a new migration yourself, or git pulled someone else's code that added a new one, it will apply them all to the database.


How to Reset

Occasionally, things will get in an ugly state and you won't be able to get out of it. When this happens, you can usually recover by running the following command: Update-Database 0. This will apply the Down methods from every migration, in the correct order, to bring you back to a completely empty database. If that succeeds, you can run Update-Database again to time travel your database back to the present.

If you're not able to do that, your final option is to connect to the database with SSMS and manually drop the database. We'll cover that in more detail when we're getting into Databases. In the meantime, feel free to google it or grab an instructor.


Migrations are Immutable once Shared

Once you've committed and pushed a migration, YOU SHOULD NEVER DELETE IT. Chances are someone else ran that migration, and if you suddenly delete the migration from the source code they won't be able to synchronize their code with their database.

Similarly, you can't modify a migration that's already been shared with other people (or applied to your own database, for that matter). You should consider them immutable once applied or shared.


Let's Migrate

Let's create some models, add some migrations and explore the generated code.

Update the database, reset the database, add some migrations and remove some migrations.

Explore the generated code along the way.