Skip to content

03 - EF Core (2)

Managing Schemas

Over time data model (entities) change and get out of sync with database. Simplest solution is to drop database and recreate in from zero. In real life - this is not usually possible; data loss is not acceptable.

EF Core provides different ways for updating database – called Migrations.

Migration

Migration include command line tools and/or code APIs:

  • Create a migration. Generate code that can update the database to sync it with a set of model changes.
  • Update the database. Apply pending migrations to update the database schema.
  • Customize migration code. Sometimes the generated code needs to be modified or supplemented.
  • Remove a migration. Delete the generated code.
  • Revert a migration. Undo the database changes.
  • Generate SQL scripts. You might need a script to update a production database or to troubleshoot migration code.
  • Apply migrations at runtime. When design-time updates and running scripts aren't the best options, call the Migrate() method.

Install/Check tooling

  • dotnet tool install --global dotnet-ef
  • dotnet tool update --global dotnet-ef
  • dotnet tool list –g
  • dotnet --version
  • dotnet --info

Add Migration

Add new/initial migration
dotnet ef migrations add InitialCreate

If needed, add options to specify startup project, project where dbcontext is and dbcontext itself (if there are several).
--project DAL --startup-project WebApp --context AppDbContext

00000000000000_InitialCreate.cs
The main migrations file. Contains the operations necessary to apply the migration (in Up()) and to revert it (in Down()).

00000000000000_InitialCreate.Designer.cs
The migrations metadata file. Contains information used by EF.

MyContextModelSnapshot.cs
A snapshot of your current model. Used to determine what changed when adding the next migration.

The timestamp in the filename helps keep them ordered chronologically

Apply Migration

Update the database
dotnet ef database update

Customize Migrations

Sometimes migration would cause data loss – some SQL operations are needed, before changing DB structure too much

The migration scaffolding process warns when an operation might result in data loss (like dropping a column). If you see that warning, be especially sure to review the migrations code for accuracy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
migrationBuilder.AddColumn<string>(
    name: "Name",
    table: "Customer",
    nullable: true
);
// CUSTOM SQL
migrationBuilder.Sql(
    @" UPDATE Customer SET Name = FirstName + ' ' + LastName;"
);
migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer"
);
migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer"
); 

Remove/Revert Migration

Sometimes you add a migration and realize you need to make additional changes to your EF Core model before applying it. To remove the last migration, use this command.

dotnet ef migrations remove

If you already applied a migration (or several migrations) to the database but need to revert it, you can use the same command to apply migrations, but specify the name of the migration you want to roll back to. (Migrations after that one will be reverted)

dotnet ef database update LastGoodMigration

Generate SQL

When debugging your migrations or deploying them to a production database, it's useful to generate a SQL script. The script can then be further reviewed for accuracy and tuned to fit the needs of a production database.

dotnet ef migrations script

Options - from, to

  • The from migration should be the last migration applied to the database before running the script. If no migrations have been applied, specify 0 (this is the default).
  • The to migration is the last migration that will be applied to the database after running the script. This defaults to the last migration in your project.

Apply migrations at runtime

Some apps may want to apply migrations at runtime during startup or first run. Do this using the Migrate() method.

  • myDbContext.Database.Migrate();
  • All unapplied migrations will be added one-by-one in sequence.

Drop the DB

If you just need to drop the database

dotnet ef database drop

If you moved your DbContext into different project you need to specify on every EF command which project is startup-project and where is DbContext

dotnet ef .... --project DAL --startup-project WebApp

Create and Drop APIs

The EnsureCreated and EnsureDeleted methods provide a lightweight alternative to Migrations for managing the database schema. These methods are useful in scenarios when the data is transient and can be dropped when the schema changes.

EnsureCreated and Migrations don't work well together. If you're using Migrations, don't use EnsureCreated to initialize the schema

The EnsureDeleted method will drop the database if it exists. dbContext.Database.EnsureDeleted();

EnsureCreated will create the database if it doesn't exist and initialize the database schema. If any tables exist (including tables for another DbContext class), the schema won't be initialized. dbContext.Database.EnsureCreated();

Async is also available!

Reverse engineering

Reverse engineering is the process of scaffolding entity type classes and a DbContext class based on a database schema.

1
2
3
4
5
6
7
dotnet ef dbcontext scaffold
"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=ContactDb”
Microsoft.EntityFrameworkCore.SqlServer
--table Persons --table Contacts --table ContactTypes
--data-annotations
--context AppDbContext
--context-dir Data --output-dir Models

String escaping according to shell you are using!