Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Database Migration Workflow in Entity Framework Core

Tech May 8 4

When utilizing the Code-First approach in Entity Framework Core, the data model rarely remains static after the initial deployment. Adding properties to entities, altering relationships, or introducing new tables requires a systematic mechanism to synchronize these structural changes with the underlying database schema without data loss.

Prerequisites

Ensure the following NuGet packages are referenced in your data access layer project:

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.x" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.x" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.x" />

The Tools package is essential as it provides the Package Manager Console commands for scaffolding migrations.

Generating Migration Scripts

Open the Package Manager Console via Tools → NuGet Package Manager → Package Manager Console. Scaffold your initial migration by executing:

Add-Migration InitialSchema

This command creates a Migrations directory containing a migration class with Up() and Down() methods, alongside a model snapshot that tracks the current state of your entities.

For subsequent schema modifications—such as adding a ModifiedAt timestamp to an existing entity—generate a new migration with a descriptive identifier:

Add-Migration AddModifiedAtToProducts

Applying Schema Changes

To execute the generated SQL commands against the target database:

Update-Database

This applies all pending migrations sequentially and records their execution in the __EFMigrationsHistory system table.

To target a specific migration (useful for rollbacks during development):

Update-Database InitialSchema

Critical Conflict: EnsureCreated vs. Migration Pipeline

A frequent pitfall arises when prototyping with EnsureCreated() or EnsureCreatedAsync():

// Anti-pattern: Bypasses the migrations system
await dbContext.Database.EnsureCreatedAsync();

This method inspects the database existence and generates the schema directly from the current model state, bypassing the migrations infrastructure antirely. If you subsequently execute Update-Database against this database, the operation fails because the migration history tracking is absent, despite the physical tables already existing.

Typical error manifestations include:

SQLite Error 1: table "Products" already exists
-- or --
SqlException: There is already an object named 'Users' in the database.

Resolution Strategy

If the database was created via EnsureCreated() but you now require migrations:

  1. Drop the existing database to eliminate the schema mismatch:

    Drop-Database
    
  2. Remove all EnsureCreated() or EnsureCreatedAsync() invocations from your startup logic.

  3. Execute the migration pipeline to recreate the database properly:

    Update-Database
    

Additional Utility Commands

To remove the most recently scaffolded migration (only if not yet applied to the database):

Remove-Migration

To generate a SQL script representing the migrations without executing them (useful for production deployment reviews):

Script-Migration

To generate a script from a specific starting point to the latest:

Script-Migration InitialSchema AddModifiedAtToProducts

Note on Legacy Commmands

Unlike Entity Framework 6, EF Core does not utilize the Enable-Migrations command. The workflow relies exclusively on Add-Migration and Update-Database. If both EF6 and EF Core tool are installed, ensure you are using the EF Core-specific command set provided by Microsoft.EntityFrameworkCore.Tools.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.