Lesson 34: EF Core Relationships, Tracking & Migrations Mastery
Master one-to-many, many-to-many, and one-to-one relationships, plus database migrations for schema evolution.
What You'll Learn
- • One-to-Many, Many-to-Many, and One-to-One relationships
- • Fluent API configuration and navigation properties
- • Migrations workflow: create, apply, revert, and remove
- • Advanced queries: filtered includes, ThenInclude, and raw SQL
🧠 Real-World Analogy
Relationships in EF Core mirror real life: an Author has many Books (one-to-many), a Book has many Tags and a Tag applies to many Books (many-to-many), and an Author has one Profile (one-to-one). Migrations are like version control for your database — each migration is a commit that can be applied or reverted.
Entity Relationships
EF Core supports three relationship types. Define them with navigation properties and configure them with Fluent API in OnModelCreating. EF Core 5+ supports skip navigations for many-to-many — no explicit join table needed.
| Relationship | Example | Configuration |
|---|---|---|
| One-to-Many | Author → Books | HasOne/WithMany + FK |
| Many-to-Many | Book ↔ Tags | HasMany/WithMany (auto join) |
| One-to-One | Author → Profile | HasOne/WithOne + FK |
Entity Relationships & Fluent API
Configure one-to-many, many-to-many, and one-to-one with Fluent API.
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
// === One-to-Many ===
public class Author
{
public int Id { get; set; }
public string Name { get; set; } = "";
public List<Book> Books { get; set; } = new(); // Navigation
}
public class Book
{
public int Id { get; set; }
public string Title { get; set; } = "";
public int AuthorId { get; set; } // Foreign key
public Author Author { get; set; } = null!; // Navigation
...Migrations
Migrations are versioned SQL scripts generated from your model changes. They have Up() (apply) and Down() (revert) methods. In production, apply migrations at startup or via CI/CD — never use EnsureCreated() in production.
Migrations Workflow
Create, apply, and revert database migrations with the EF CLI.
// === EF Core Migrations Workflow ===
// Migrations track database schema changes over time
// 1. Create initial migration
// dotnet ef migrations add InitialCreate
// Generated migration file:
using Microsoft.EntityFrameworkCore.Migrations;
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Authors",
columns: table => new
{
Id
...Advanced Queries
Use ThenInclude for multi-level eager loading, filtered includes for conditional loading, and fall back to raw SQL when LINQ can't express your query efficiently.
Multi-Level Include & Filtered Queries
Load nested relationships and use filtered includes for targeted data loading.
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
class Program
{
static void Main()
{
using var db = new LibraryContext();
db.Database.EnsureCreated();
// Seed data
if (!db.Authors.Any())
{
var tag1 = new Tag { Name = "Fiction" };
var tag2 = new Tag { Name = "Science" };
var tag3 = new Tag { Name = "Classic" };
db.Authors.AddRange(
new Author
...Pro Tip
Use db.Database.Migrate() in Program.cs to auto-apply pending migrations at startup. For production, consider generating SQL scripts with dotnet ef migrations script and applying them through your CI/CD pipeline.
Common Mistakes
- • Using
EnsureCreated()with migrations — they're mutually exclusive - • Deleting migration files manually — use
dotnet ef migrations remove - • Cascade deleting unintentionally — always specify
OnDeletebehavior
Lesson Complete!
You've mastered EF Core relationships and migrations. Next, implement the Repository Pattern and Unit of Work for clean architecture.
Sign up for free to track which lessons you've completed and get learning reminders.