Today, I want to share a bit of my journey while working on a real-world project where I had to manage database changes properly using Entity Framework Core. I know, “migrations” might sound a bit intimidating at first, especially if you’re new to EF Core or you haven’t handled schema evolution yet. Believe me, I was also there once, scratching my head. So let’s go through this together, like how I learned it (sometimes the hard way).
First Things First: What is EF Core Migration?
Imagine you already have your application running, and suddenly the client asks you to add a new feature, like “store the user’s birthday.” That means your database needs a new column.
Migrations help you update your database schema without needing to manually alter tables every time you make a change in your model classes. It’s a version control for your database structure.
Simply put: Migrations = Model changes -> SQL Changes -> Database updated automatically.
Why Migrations Matter?
In my project, we started simple. Just a few tables. At first, I thought, “I will just manually edit my tables in SQL Server, no big deal.” But when the project grew, I realized I was creating a monster. Production data, test data, different environments… it was getting messy. Sometimes an ALTER TABLE command missed, sometimes the developer’s local database was different from the staging server. Disaster waiting to happen!
Once I started using EF Core Migrations properly, everything became smoother. And safer. My team members could update their databases consistently without worries.
Setting Up Migrations in EF Core
Alright, let’s get our hands a bit dirty.
Step 1: Install Required Packages
If you haven’t installed these yet, make sure your project has:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer (or your database provider)
You can install via NuGet Package Manager or simply:
dotnet add package Microsoft.EntityFrameworkCore.Design
Step 2: Create Your DbContext and Models
Example:
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Your_Connection_String_Here");
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
In this example, AppDbContext is the bridge between your application and your database. It inherits from DbContext, which is a base class provided by EF Core that gives you all the functionality needed to interact with the database. Inside it, we declare a DbSet named Users, which represents a table where each User object is a row in the database. The OnConfiguring method tells EF Core how to connect to your database, in this case, it uses SQL Server, and you specify your connection string here. Later on, for better practice and cleaner code, you can move your connection strings to a configuration file like appsettings.json instead of hardcoding them.
Step 3: Add Your First Migration
Run this command:
dotnet ef migrations add InitialCreate
This will create a Migrations folder with a snapshot of your database schema.
Step 4: Apply the Migration
Run:
dotnet ef database update
Boom! Your database is created based on your models.
A Small Real-World Scenario
In our project, one day we needed to add a DateOfBirth field for Users.
We just:
1. Update the model.
public DateTime? DateOfBirth { get; set; }
2. Added a new migration.
dotnet ef migrations add AddDateOfBirthToUser
3. Update the database.
dotnet ef database update
That’s it. No manual ALTER TABLE. No forgetting a field. Everyone on the team ran the same migrations.
Common Migration Commands You Should Know
Here are a few I personally used a lot:
Add Migration
dotnet ef migrations add MigrationName
Remove Last Migration
dotnet ef migrations remove
Update Database
dotnet ef database update
Script Migration (for manual deployment)
dotnet ef migrations script
Tips and Things I Learned the Hard Way
1. Never Edit Migration Files Manually (if not expert)
They are auto-generated for a reason. If you must tweak something, better rollback and re-create the migration cleanly.
2. Keep Migration Names Clear
Use meaningful names like AddDateOfBirthToUser instead of Update1, NewMigration2, etc. Future you will thank you.
3. Be Careful on Production Databases
On live systems, running migrations blindly can cause downtime. Always test migrations first on a clone database.
4. Migration History is Stored
EF Core tracks applied migrations inside a special table called __EFMigrationsHistory.
Applying Migrations Automatically (Careful!)
Sometimes, especially in small apps or internal tools, you might want your app to apply migrations automatically at startup.
Add this in your Program.cs:
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
db.Database.Migrate();
}
This will apply any pending migrations automatically when the app starts. Use it wisely.
Useful Resources
If you want to deep dive more, here are official and excellent references I personally studied too:
- Microsoft Docs – EF Core Migrations Overview
- Microsoft Docs – EF Core Tools Reference
- Official GitHub Samples
Please check them out if you want to become really good in EF Core!