Lesson 33: Entity Framework Core Internals & Performance
Understand how EF Core tracks entities, generates SQL, and how to write efficient database queries.
What You'll Learn
- • DbContext, DbSet, and entity configuration
- • LINQ-to-SQL translation and eager/lazy loading
- • Change tracking states (Added, Modified, Unchanged, Deleted)
- • AsNoTracking, projections, and performance best practices
🧠 Real-World Analogy
EF Core is like a personal assistant who translates between you (C#) and a foreign business partner (the database). You say "find products over $100 sorted by name" in C#, and the assistant writes the SQL query, sends it, and hands you back C# objects. Change tracking is like the assistant keeping a notepad of everything you changed, then sending all updates at once when you say "save."
DbContext & Entity Configuration
DbContext is the central class in EF Core. It represents a session with the database, holds DbSet<T> properties for each table, and manages change tracking. You configure entities with Data Annotations on the class or Fluent API in OnModelCreating.
DbContext, Entities & Fluent API
Set up a database context with entity configuration and seed data.
using System;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
// Entity classes
public class Product
{
public int Id { get; set; }
[Required, MaxLength(100)]
public string Name { get; set; } = "";
public decimal Price { get; set; }
[MaxLength(50)]
public string Category { get; set; } = "";
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
// Navigation property (one-to-many)
public List<Revie
...LINQ Queries & Loading Strategies
EF Core translates LINQ expressions to SQL. Use Include() for eager loading related data, Select() for projections (fetching only needed columns), and AsNoTracking() for read-only queries that skip change tracking overhead.
LINQ Queries, Include & Projections
Write efficient queries with eager loading, projections, and AsNoTracking.
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
// Assume AppDbContext from previous example
class Program
{
static void Main()
{
using var db = new AppDbContext();
db.Database.EnsureCreated();
// === Basic LINQ queries (translated to SQL) ===
// SELECT * FROM Products WHERE Price > 100 ORDER BY Name
var expensive = db.Products
.Where(p => p.Price > 100)
.OrderBy(p => p.Name)
...Change Tracking
EF Core's change tracker monitors every entity loaded from the database. When you modify properties, it detects the changes automatically. SaveChanges() generates the minimal SQL needed — only UPDATE the columns that actually changed.
Change Tracking States & SaveChanges
Observe entity states and see how EF Core generates minimal SQL.
using System;
using Microsoft.EntityFrameworkCore;
class Program
{
static void Main()
{
using var db = new AppDbContext();
db.Database.EnsureCreated();
// === Change Tracking — EF tracks entity state ===
Console.WriteLine("=== Change Tracking Demo ===
");
// 1. Load an entity (state: Unchanged)
var product = db.Products.First();
Console.WriteLine($"Loaded: {product.Name} (State: {db.Entry(product).State})");
...| Entity State | Meaning | SQL Generated |
|---|---|---|
| Added | New entity, not yet in DB | INSERT |
| Unchanged | Loaded, not modified | None |
| Modified | Property values changed | UPDATE (changed cols only) |
| Deleted | Marked for removal | DELETE |
| Detached | Not tracked by context | None |
Pro Tip
Use ExecuteUpdate and ExecuteDelete (EF Core 7+) for bulk operations that bypass change tracking entirely. They translate directly to UPDATE/DELETE SQL without loading entities into memory.
Common Mistakes
- • N+1 queries — forgetting
Include()causes a query per related entity - • Loading entire entities when you only need 2 columns — use
Select() - • Long-lived DbContext — keep it short-lived (scoped per request)
Lesson Complete!
You understand EF Core's internals. Next, master relationships, tracking strategies, and migrations.
Sign up for free to track which lessons you've completed and get learning reminders.