Entity Relationships in EF Core
Real-world data is rarely isolated. Customers place orders, authors write blog posts, and students enroll in courses. EF Core lets you model these connections between entities so that your C# object graph mirrors the actual relationships in your database.
Why Relationships Matter
Without relationships, you would store everything in flat, disconnected tables and manually join data with raw SQL. EF Core relationships give you:
- Object navigation: Access related data through properties like
blog.Postsinstead of writing JOIN queries - Automatic foreign keys: EF Core creates and manages FK columns for you
- Cascade operations: Deleting a parent can automatically delete its children
- Query integration: Use LINQ to filter and include related data in a single query
csharp1// Without relationships - manual join2var posts = await context.Posts3 .Where(p => p.BlogId == blogId)4 .ToListAsync();56// With relationships - navigation property7var blog = await context.Blogs8 .Include(b => b.Posts)9 .FirstOrDefaultAsync(b => b.Id == blogId);1011// Now blog.Posts contains all related posts
Types of Relationships
EF Core supports three fundamental relationship types that map directly to relational database concepts:
One-to-Many (1:N)
The most common relationship. One entity is associated with many instances of another entity.
1┌──────────┐ ┌──────────┐2│ Blog │ 1───* │ Post │3│ │ │ │4│ Id │ │ Id │5│ Name │ │ Title │6│ │ │ BlogId │ ← Foreign key7└──────────┘ └──────────┘
Examples: A blog has many posts. A department has many employees. A customer has many orders.
One-to-One (1:1)
Each entity is associated with at most one instance of the other entity.
1┌──────────┐ ┌─────────────┐2│ User │ 1───1 │ UserProfile │3│ │ │ │4│ Id │ │ Id │5│ Email │ │ Bio │6│ │ │ UserId │ ← Foreign key7└──────────┘ └─────────────┘
Examples: A user has one profile. An order has one shipping address. A country has one capital city.
Many-to-Many (N:M)
Each entity can be associated with multiple instances of the other entity.
1┌──────────┐ ┌───────────┐ ┌──────────┐2│ Student │ *───* │ Enrolled │ *───* │ Course │3│ │ │ (join) │ │ │4│ Id │ │ StudentId │ │ Id │5│ Name │ │ CourseId │ │ Title │6└──────────┘ └───────────┘ └──────────┘
Examples: Students enroll in many courses, and each course has many students. Posts can have many tags, and each tag applies to many posts.
Navigation Properties
Navigation properties are the C# mechanism for traversing relationships. They come in two forms:
Reference Navigation
Points to a single related entity. Used on the "many" side of a one-to-many or either side of a one-to-one relationship.
csharp1public class Post2{3 public int Id { get; set; }4 public string Title { get; set; } = string.Empty;56 // Reference navigation to the parent Blog7 public Blog Blog { get; set; } = null!;8}
Collection Navigation
Points to a collection of related entities. Used on the "one" side of a one-to-many relationship.
csharp1public class Blog2{3 public int Id { get; set; }4 public string Name { get; set; } = string.Empty;56 // Collection navigation to child Posts7 public ICollection<Post> Posts { get; set; } = new List<Post>();8}
Foreign Key Properties
A foreign key property stores the ID of the related entity. EF Core can infer foreign keys by convention, but you can also declare them explicitly for clarity:
csharp1public class Post2{3 public int Id { get; set; }4 public string Title { get; set; } = string.Empty;56 public int BlogId { get; set; } // Foreign key property7 public Blog Blog { get; set; } = null!; // Navigation property8}
Declaring the FK property gives you direct access to the related entity's ID without loading the full entity.
How EF Core Discovers Relationships
EF Core uses conventions to detect relationships automatically:
- Navigation property detected - EF Core sees
Blogproperty onPost - Inverse navigation matched - It pairs
Post.BlogwithBlog.Posts - Foreign key inferred - It looks for a property named
BlogIdorBlogFK - Relationship configured - One-to-many from
BlogtoPostviaBlogId
When conventions are not sufficient, you can use the Fluent API in OnModelCreating to configure relationships explicitly. We will cover each configuration approach in the following presentations.
Summary
In this lesson, you learned:
- Relationships connect entities and enable navigation between related data
- EF Core supports one-to-many, one-to-one, and many-to-many relationships
- Navigation properties (reference and collection) let you traverse relationships in C#
- Foreign key properties store the related entity's ID in the database
- EF Core discovers most relationships automatically through conventions
Next, we will dive deep into each relationship type, starting with one-to-many.