5. Entity Framework Core

ASP.NET Core Entity Framework Core - Complete Guide

Practical Guide + Technical Reference


📋 Table of Contents

Part 1: Practical Guide (Hands-On)

  1. EF Core Basics

  2. 3 Ways to Set Up EF Core

  3. DbContext Essentials

  4. Defining Models

  5. CRUD Operations

  6. Migrations

  7. Relationships

  8. Querying Patterns

  9. Troubleshooting Common Issues

  10. Best Practices

Part 2: Technical Reference (Deep Dive)

  1. Important Interfaces & Classes Reference

  2. Configuration Deep-Dive

  3. Advanced Topics

  4. Performance Optimization


PART 1: PRACTICAL GUIDE


1. EF Core Basics

Simple Definition: Entity Framework Core is an ORM (Object-Relational Mapper) that lets you work with databases using C# objects instead of SQL.

Think of it like: A translator between your C# code and the database. You work with regular C# classes, and EF Core handles all the SQL behind the scenes.

What is an ORM?

Without ORM (Raw SQL):

With ORM (EF Core):

Code-First vs Database-First

Approach
When to Use
Starting Point

Code-First 🎯

New projects, full control

Write C# classes → Generate database

Database-First

Legacy databases, existing DB

Database exists → Generate C# classes

This guide focuses on Code-First (most common for new ASP.NET Core projects)

When to Use EF Core

Use EF Core when:

  • Building CRUD applications

  • Working with relational databases (SQL Server, PostgreSQL, MySQL)

  • Need type-safe queries

  • Want automatic change tracking

  • Prefer C# over SQL

Don't use EF Core when:

  • Need maximum performance (use Dapper)

  • Complex stored procedures (better in SQL)

  • Very simple read-only queries (use ADO.NET)

  • NoSQL databases (use native drivers)

EF Core Evolution Timeline


2. 3 Ways to Set Up EF Core

When to use:

  • ✅ Production applications

  • ✅ Team development

  • ✅ Enterprise projects

  • ✅ Windows or Azure hosting

Step 1: Install NuGet Package

Step 2: Create DbContext

Step 3: Configure Connection String

Step 4: Register DbContext in Program.cs

Step 5: Create Initial Migration

Step 6: Update Database

Complete Working Example:


Method 2: SQLite (Development & Learning) 📚 GREAT FOR LEARNING

When to use:

  • ✅ Local development

  • ✅ Learning EF Core

  • ✅ Testing/prototyping

  • ✅ Lightweight applications

  • ✅ No database server needed

Step 1: Install Package

Step 2: Connection String

Step 3: Register DbContext

Step 4: Create & Run Migrations

Complete SQLite Example:

Advantages:

  • Zero configuration

  • File-based (app.db)

  • Perfect for demos

  • Works everywhere


Method 3: In-Memory Database (Testing) 🧪

When to use:

  • ✅ Unit testing

  • ✅ Integration testing

  • ✅ Temporary data

  • ❌ NOT for production

Step 1: Install Package

Step 2: Configure In-Memory Database

Complete Testing Example:


Database Provider Comparison

Provider
NuGet Package
Connection String Example
Best For

SQL Server

EntityFrameworkCore.SqlServer

Server=.;Database=MyDb;...

Production

PostgreSQL

Npgsql.EntityFrameworkCore.PostgreSQL

Host=localhost;Database=mydb;...

Open source

MySQL

Pomelo.EntityFrameworkCore.MySql

server=localhost;database=mydb;...

LAMP stack

SQLite

EntityFrameworkCore.Sqlite

Data Source=app.db

Development

In-Memory

EntityFrameworkCore.InMemory

InMemoryDatabase("TestDb")

Testing


3. DbContext Essentials

What is DbContext?

DbContext is your gateway to the database. It:

  • Represents a session with the database

  • Tracks changes to entities

  • Manages database connections

  • Executes queries and commands

Think of it like: A shopping cart that tracks what you want to buy (add/modify/delete) and commits all changes at once when you checkout (SaveChanges).

Basic DbContext Structure

DbSet Properties

This one line creates:

  • A table named "Users"

  • Queryable collection of User entities

  • Add/Remove/Update capabilities

OnConfiguring vs OnModelCreating

Method
Purpose
When to Use

OnConfiguring

Configure DbContext options

Rarely (use DI instead)

OnModelCreating

Configure entity mappings

Always (Fluent API)

OnConfiguring (Avoid in ASP.NET Core):

OnModelCreating (Use This):

3 Ways to Configure DbContext

Configuration Method 1: Inline/Hardcoded (Quick Testing)

Pros: Quick, simple Cons: Hardcoded, insecure, can't change environments


Configuration Method 2: From Configuration (Standard) 🎯

Pros: Environment-specific (appsettings.Development.json, appsettings.Production.json) Cons: Connection string visible in config


Configuration Method 3: With Options Pattern (Advanced)

Pros: Type-safe, testable, flexible Cons: More complex


Complete DbContext Example


4. Defining Models (Entity Classes)

Simple Entity

Primary Key Conventions

EF Core automatically recognizes these as primary keys:

  • Property named Id

  • Property named {ClassName}Id (e.g., UserId for User class)

3 Ways to Define Primary Key:

Method 1: By Convention (Simple)

Method 2: Data Annotations

Method 3: Fluent API (Flexible) 🎯


Data Annotations

Common Data Annotations:

Annotation
Purpose

[Key]

Primary key

[Required]

NOT NULL constraint

[StringLength(100)]

VARCHAR(100)

[MaxLength(500)]

Maximum length

[MinLength(10)]

Minimum length

[EmailAddress]

Email format validation

[Phone]

Phone format

[Range(1, 100)]

Value range

[Column(TypeName = "decimal(18,2)")]

SQL type

[Table("Users")]

Table name

[NotMapped]

Exclude from DB

[ForeignKey("UserId")]

Foreign key


One-to-Many Example:

How to Use:


Complete Model Examples


5. CRUD Operations

Create (C)

Add Single Entity

Add Multiple Entities

Complete Create Example


Read (R)

Find by ID

Query with LINQ

Eager Loading (Include)

Lazy Loading ✨ EF Core 2.1+

⚠️ Lazy Loading Warning: Can cause N+1 query problems. Use with caution.

Complete Read Examples


Update (U)

Modify Existing Entity

Attach and Modify (Disconnected Scenario)

Update Specific Properties

Complete Update Example


Delete (D)

Remove Entity

Remove Without Loading

Soft Delete

Complete Delete Example


6. Migrations

What are Migrations?

Migrations are version control for your database schema. They track changes to your models and update the database to match.

Think of it like: Git for your database. Each migration is like a commit that describes what changed.

Migration Workflow

3 Methods to Create Migrations

Method 1: .NET CLI (Recommended) 🎯


Method 2: Package Manager Console (Visual Studio)


Method 3: Code-Based Migration (Advanced)


Creating Migrations Step-by-Step

Step 1: Modify Your Model

Step 2: Create Migration

This creates:

  • Migrations/20241220_AddPhoneToUser.cs - Migration code

  • Migrations/ApplicationDbContextModelSnapshot.cs - Current model state

Step 3: Review Generated Code

Step 4: Apply Migration


Applying Migrations

Development Environment

Production Environment (Recommended)

Auto-Apply on Startup (Development Only)


Rolling Back Migrations


Seed Data


Production Migrations Best Practices

Deployment Process:

  1. Review SQL script

  2. Test on staging environment

  3. Apply during maintenance window

  4. Never auto-migrate in production!


7. Relationships

One-to-Many Relationship

Example: One User has many Orders

3 Ways to Configure:

Method 1: By Convention (Simplest)

EF Core automatically detects:

  • Navigation properties (Orders, User)

  • Foreign key (UserId)

  • Creates relationship


Method 2: Data Annotations


Method 3: Fluent API (Most Control) 🎯

Complete One-to-Many Example:


One-to-One Relationship

Example: User has one Profile

Configuration (Fluent API):

Complete One-to-One Example:


Many-to-Many Relationship ✨ EF Core 5.0+

Example: Students enroll in many Courses, Courses have many Students

Method 1: Skip Navigation (EF Core 5.0+) 🎯 RECOMMENDED


Method 2: Explicit Join Entity (More Control)


Relationship Delete Behaviors

Behavior
What Happens

Cascade

Delete dependent (Orders) when principal (User) deleted

Restrict

Prevent delete if dependent exists

SetNull

Set foreign key to NULL

NoAction

Do nothing (database constraint handles it)


8. Querying Patterns

AsNoTracking (Read-Only Queries)

When to use:

  • ✅ Read-only queries (GET endpoints)

  • ✅ Reports, dashboards

  • ✅ Any time you won't modify entities

  • ❌ If you need to update data


Projection (Select)


Filtering (Where)


Sorting (OrderBy)


Pagination (Skip/Take)


GroupBy


Complete Querying Example


9. Troubleshooting Common Issues

Issue 1: No Database Provider Configured

Problem:

Solution:


Issue 2: Entity Not Tracked

Problem:

Solution:


Issue 3: N+1 Query Problem

Problem:

Solution:


Issue 4: Lazy Loading Not Working

Problem:

Solution:


Issue 5: Migrations Not Applying

Problem:

Solution:


Issue 6: Connection String Not Found

Problem:

Solution:


Issue 7: Tracking Multiple Instances

Problem:

Solution:


10. Best Practices

✅ DO

  1. Use AsNoTracking for read-only queries

  2. Always use async/await

  3. Use Include for eager loading

  4. Project to DTOs

  5. Use migrations for schema changes

  6. Configure relationships with Fluent API

  7. Use scoped lifetime for DbContext


❌ DON'T

  1. Don't use DbContext as singleton

  2. Don't call SaveChanges in loops

  3. Don't load entire tables

  4. Don't forget using statements (if not using DI)

  5. Don't expose DbContext directly in APIs


Performance Tips

  1. Use compiled queries for frequently used queries ✨ EF Core 2.0+

  2. Batch operations ✨ EF Core 7.0+

  3. Use DbContext pooling

  4. Split queries for large includes ✨ EF Core 5.0+


PART 2: TECHNICAL REFERENCE


11. Important Interfaces & Classes Reference

DbContext Class ⭐⭐⭐

Purpose: Represents a session with the database and provides APIs for CRUD operations

Namespace: Microsoft.EntityFrameworkCore

Key Members:

Member
Type
Description

Database

DatabaseFacade

Database operations (Migrate, BeginTransaction)

ChangeTracker

ChangeTracker

Tracks entity changes

Model

IModel

Database model metadata

SaveChanges()

int

Persist changes to database (returns affected rows)

SaveChangesAsync()

Task

Async version

Add<T>()

EntityEntry

Start tracking entity in Added state

Update<T>()

EntityEntry

Start tracking entity in Modified state

Remove<T>()

EntityEntry

Start tracking entity in Deleted state

Attach<T>()

EntityEntry

Start tracking entity in Unchanged state

Entry<T>()

EntityEntry

Access entity state and metadata

Find<T>()

T

Find entity by primary key

FindAsync<T>()

Task

Async version

Important Methods:

Configuration:


DbSet Class ⭐⭐⭐

Purpose: Represents a collection of entities (table)

Namespace: Microsoft.EntityFrameworkCore

Key Members:

Member
Return Type
Description

Add(entity)

EntityEntry

Add entity

AddAsync(entity)

Task<EntityEntry>

Async add

AddRange(entities)

void

Add multiple entities

Remove(entity)

EntityEntry

Remove entity

RemoveRange(entities)

void

Remove multiple

Update(entity)

EntityEntry

Update entity

UpdateRange(entities)

void

Update multiple

Find(key)

T

Find by primary key

FindAsync(key)

Task

Async find

LINQ Methods (from IQueryable):

Method
Description

Where()

Filter

Select()

Projection

OrderBy()

Sort ascending

OrderByDescending()

Sort descending

Skip()

Skip records (pagination)

Take()

Take records (pagination)

Include()

Eager load related data

ThenInclude()

Nested eager loading

AsNoTracking()

Disable change tracking

FirstOrDefaultAsync()

Get first or null

SingleOrDefaultAsync()

Get single or null

ToListAsync()

Execute and return list

CountAsync()

Count records

AnyAsync()

Check if any exist

Usage Examples:


ModelBuilder Class ⭐⭐

Purpose: Fluent API for configuring entity models

Namespace: Microsoft.EntityFrameworkCore

Key Methods:

Method
Purpose

Entity<T>()

Configure entity

HasKey()

Define primary key

HasOne()

Configure one side of relationship

HasMany()

Configure many side of relationship

Property()

Configure property

HasIndex()

Create index

HasData()

Seed data

HasQueryFilter()

Global query filter

Complete Example:


ChangeTracker Class

Purpose: Tracks entity changes

Namespace: Microsoft.EntityFrameworkCore.ChangeTracking

Key Members:

Member
Description

Entries()

Get all tracked entities

Entries<T>()

Get tracked entities of type T

Clear()

Stop tracking all entities

HasChanges()

Check if any changes

DetectChanges()

Manually detect changes

Usage:


EntityEntry Class

Purpose: Access entity state and metadata

Key Properties:

Property
Description

State

EntityState (Added, Modified, Deleted, Unchanged)

Entity

The tracked entity

OriginalValues

Original property values

CurrentValues

Current property values

Usage:


Entity States

State
Description
When

Detached

Not tracked

Entity created without context

Unchanged

Tracked, no changes

After query or SaveChanges

Added

Tracked, will be inserted

After Add()

Modified

Tracked, will be updated

After modifying tracked entity

Deleted

Tracked, will be deleted

After Remove()

State Diagram:


12. Configuration Deep-Dive

OnModelCreating Patterns

Pattern 1: Inline Configuration

Pros: Simple, all in one place Cons: Gets messy with many entities


Pattern 2: Configuration Classes (IEntityTypeConfiguration) 🎯 RECOMMENDED

Pros: Clean, organized, one file per entity Cons: More files


Pattern 3: Extension Methods


Fluent API Complete Reference

Table Configuration

Primary Key

Properties

Indexes

Relationships


Global Query Filters


Value Conversions ✨ EF Core 2.1+


Owned Entities ✨ EF Core 2.0+


Table Splitting


13. Advanced Topics

Raw SQL Queries


Stored Procedures


Concurrency Handling


Shadow Properties


Interceptors ✨ EF Core 3.0+


DbContext Pooling ✨ EF Core 2.0+

Benefits:

  • Reuses DbContext instances

  • Reduces overhead of creating new contexts

  • Improves performance in high-traffic apps

Limitations:

  • DbContext state must be reset between requests

  • Can't use constructor DI for dependencies


14. Performance Optimization

Query Performance Tips


Batch Operations ✨ EF Core 7.0+


Connection Resiliency


Monitoring and Logging


Summary

This guide covered:

  • ✅ EF Core setup (SQL Server, SQLite, In-Memory)

  • ✅ DbContext configuration (3 methods)

  • ✅ Model definition and data annotations

  • ✅ Complete CRUD operations

  • ✅ Migrations workflow

  • ✅ Relationships (one-to-many, one-to-one, many-to-many)

  • ✅ Advanced querying patterns

  • ✅ Troubleshooting common issues

  • ✅ Best practices

  • ✅ Performance optimization

Next Steps:

  • Practice with a real project

  • Explore EF Core advanced features

  • Learn about repository pattern

  • Study performance optimization


Version: ASP.NET Core 8.0 Created: December 2024 Target: Developers learning Entity Framework Core

Last updated