This is the seventh of a new series of posts on ASP .NET Core. In this post, we’ll be looking at the use of EF Core Migrations for your ASP .NET Core web apps. (Normally, I would publish these blog posts on a weekend to allow developers to read it the following week. However, it’s Thanksgiving next week in the US, so I’m publishing this one a few days earlier.)
Entity Framework Core
Entity Framework is Microsoft’s ORM (Object-Relational Mapper) and EF Core is a lightweight, cross-platform version of EF, useful for ASP .NET Core web app developers. This article isn’t going to try and convince you of the benefits of using an ORM. If you’re reading this article, hopefully you’ll already recognize the value of using an ORM for your web app.
Instead, we’ll be focusing on EF Core Migrations for taking control of your database. By using migrations, you’ll be able to add and manipulate database objects, define relationships between entities and help developers and server environments stay in sync with specific versions of your database schema.
Commands for Migrations
You can add migrations to your ASP .NET Core web app project in a number of ways, including the following:
- PowerShell commands within the Package Manager Console in Visual Studio
- CLI commands from a Command Line or VS Code’s Terminal
We will cover both approaches in this article. Each auto-generated Migration class will contain at least an Up() method and a Down() method to encapsulate commands to update and revert a database, respectively.
Adding a Migration
When you make some Model changes that you’d like to group together in a single Migration, you can add a new migration using the following command.
PowerShell Command
Add-Migration <migration-name>
CLI Command:
dotnet ef migrations add <migration-name>
This will create a new migration with the specified <migration-name> and add a class with that name in your Migrations subfolder. In the NetLearning repo from the last blog post, check out the LearningResourceModelAndPages migration to see an example. Note that the class filename contains a combination of a datetime stamp followed by the <migration-name>. However, the class name itself is only the friendly name <migration-name>, which makes it easier to read.
Migrations folder: https://github.com/shahedc/NetLearner/tree/master/web/Data/Migrations
Updating the Database
After a new migration has been added, your migration code will become out of sync with your database. To update your database, you will have to run the following command.
PowerShell Command
Update-Database
CLI Command:
dotnet ef database update
Each developer will typically run this command in their own development environment, which could be pointing to a LocalDB instance, SQL Server instance on your network, in the cloud, etc.
Removing a Migration
If you need to revert some changes for any reason (nobody’s perfect!), you can do this by removing the last migration, as long as you have haven’t applied the database update yet. You may have to do this if you made some mistakes, and have to make some more changes to the migration before updating the database. Removing the last migration may also be needed if you intend to remove the migration without replacing it.
PowerShell Command
Remove-Migration
CLI Command:
dotnet ef migrations remove
But what if you have already applied one or more migrations to the database? What then? Fortunately, you can revert a database to a specific migration.
PowerShell Command
Update-Database <specific-migration>
CLI Command:
dotnet ef database update <specific-migration>
Note that this is the same command to update the database, but with an additional parameter with the value of the specific migration to revert to.
Running in Production
If you share all of the above information with a DBA on your team, they may stare at you in disbelief if you try to run automatic database migrations in production. So what’s a developer to do?
Fear not, SQL Scripts to rescue! Use the following command to generate the equivalent SQL Script for your migration(s). Such a script can be manually inspected (and even revised further for optimization, if necessary) for the DBA or company’s needs. Note that database updates can be used in your CI/CD environment to ensure that your various environments are updated when all tests are passing, and your app is ready for the next deployment.
PowerShell Command
Script-Migration
CLI Command:
dotnet ef migrations script
Wait a minute, how does it know which migration(s) to create scripts for? There are optional parameters called From and To that have default values. These determine where to start and where to end. These parameter flags are explained below:
- From: the migration to start from, identified by numeric Id or friendly name. Defaults to 0, which makes it start before the first migration.
- To: the migration to end on, identified by numeric Id or friendly name. Defaults to the last available migration.
Script-Migration -To <starting-migration> Script-Migration -From <ending-migration>
If you need to apply the SQL Script to any database at any migration, you may include the Idempotent flag as well.
- Idempotent: this optional flag doesn’t require any further instructions and will help you generate a SQL Script that can be used on a database at any migration.
Finally, you can dump the generated SQL Script into a file using the Output flag.
Script-Migration -Output "myMigrations.sql"
Now, what if there are any requirements for database entities and constraints to be named with a specific syntax that is different from your C# model class names? Not to worry, there’s a way to fix this with Table Mapping! You could use attribute-based Data Annotations or code-based Fluent API.
- More information on Table Mapping: https://docs.microsoft.com/en-us/ef/core/modeling/relational/tables
Reverting ALL Migrations
To revert all your migrations, you may update the database using the default value of 0 for the -Migration flag with the command for updating a database.
Update-Database -Migration 0
Bonus: Good to Know
When learning EF Core, you may come across the EnsureCreated method. This method ensures that the database exists, by creating the entire database only if the database doesn’t already exist. As you can imagine, this is not very useful for use with migrations. In fact, a database generated using EnsureCreated can’t even be updated using migrations.
So what is EnsureCreated good for? You may see it in some tutorials as a starting point in your project. It may be useful to use it while your schema is still evolving on a new project. See the following EF Core tutorial for such an example, which is also a great place to get started with an intro tutorial:
- Razor Pages with EF Core: https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/intro?view=aspnetcore-2.1&tabs=visual-studio
Next Steps
After trying the EF Core tutorial mentioned above, don’t forget to stop by Pluralsight to watch Julie Lerman‘s EF videos. You can get started with a free trial, pay for a subscription or ask your employer if they can provide an employee subscription. Julie also has many EF articles in MSDN Magazine as well.
- Julie Lerman on Pluralsight: https://www.pluralsight.com/authors/julie-lerman
- EF Core 2 – Getting Started: https://www.pluralsight.com/courses/entity-framework-core-2-getting-started
- EF Core 2 – Mappings: https://www.pluralsight.com/courses/e-f-core-2-beyond-the-basics-mappings
- EF Core 2.1 – What’s New: https://www.pluralsight.com/courses/playbook-ef-core-2-1-whats-new
- Logging SQL and Change-Tracking Events in EF Core: http://msdn.microsoft.com/magazine/mt830355
- Deep Dive into EF Core HasData Seeding: http://msdn.microsoft.com/magazine/mt829703
- EF Core 2.1 Query Types: http://msdn.microsoft.com/magazine/mt847184
References
- EF Intro with MVC: https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/migrations?view=aspnetcore-2.1
- EF Intro with RP: https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/intro?view=aspnetcore-2.1&tabs=visual-studio
- Migrations: https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/migrations?view=aspnetcore-2.1&tabs=visual-studio
- Migrations – EF Core (docs): https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/
- EF Core tools reference (.NET CLI): https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet
Pingback: Dew Drop - November 26, 2018 (#2846) - Morning Dew
Pingback: Authentication & Authorization in ASP .NET Core Razor Pages | Wake Up And Code!
Pingback: EF Core Relationships in ASP .NET Core | Wake Up And Code!
Pingback: Zero-Downtime* Web Apps for ASP .NET Core | Wake Up And Code!
Pingback: Authentication & Authorization in ASP .NET Core 3.1 | Wake Up And Code!
Pingback: Production Tips for ASP .NET Core 3.1 Web Apps | Wake Up And Code!
Pingback: Zero-Downtime* Web Apps for ASP .NET Core 3.1 | Wake Up And Code!