█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/Programming Languages/C# and .NET/Entity Framework Core
65 minIntermediate

Entity Framework Core

After this lesson, you will be able to: Use Entity Framework Core: code-first migrations, DbContext, LINQ queries, relationships, performance traps.

EF Core is the standard .NET ORM. Code-first migrations + LINQ queries that translate to SQL = productive but with footguns around N+1 and lazy loading.

Prerequisites:ASP.NET Core

Define models + DbContext

Models are POCOs; DbContext is your unit of work.

html
// Models
public class User {
public int Id { get; set; }
public string Name { get; set; } = "";
public string Email { get; set; } = "";
public List<Post> Posts { get; set; } = new();
}
public class Post {
public int Id { get; set; }
public string Title { get; set; } = "";
public int UserId { get; set; }
public User User { get; set; } = null!;
}
// DbContext
public class AppDbContext : DbContext {
public DbSet<User> Users => Set<User>();
public DbSet<Post> Posts => Set<Post>();
protected override void OnConfiguring(DbContextOptionsBuilder options) {
options.UseNpgsql("Host=localhost;Database=mydb;Username=postgres;Password=...");
// Or: options.UseSqlServer(connStr) / UseSqlite(connStr)
}
}
// In Program.cs
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("Default")));

Migrations + database create

Code-first workflow.

tsx
# Install EF tool (one-time)
dotnet tool install --global dotnet-ef
# Add EF Core packages
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Npgsql
# Add a migration
dotnet ef migrations add InitialCreate
# Apply to database
dotnet ef database update
# Roll back
dotnet ef migrations remove
# Generate SQL script (don't apply)
dotnet ef migrations script

Querying with LINQ → SQL

LINQ queries translate to SQL automatically.

tsx
using var db = new AppDbContext();
// Simple find
var user = await db.Users.FindAsync(1);
// Where + Select (translates to SQL)
var names = await db.Users
.Where(u => u.Name.StartsWith("A"))
.Select(u => u.Name)
.ToListAsync();
// Eager loading (avoids N+1)
var usersWithPosts = await db.Users
.Include(u => u.Posts)
.ToListAsync();
// Async paging
var page = await db.Users
.OrderBy(u => u.Name)
.Skip(10).Take(10)
.ToListAsync();
// Insert
db.Users.Add(new User { Name = "Sam", Email = "[email protected]" });
await db.SaveChangesAsync();
// Update, change tracker auto-detects changes
var u = await db.Users.FindAsync(1);
u!.Email = "[email protected]";
await db.SaveChangesAsync();
// Delete
db.Users.Remove(u);
await db.SaveChangesAsync();

💡 The N+1 trap

If you forget `.Include(u => u.Posts)` and then iterate `u.Posts`, EF Core lazy-loads each user's posts in a SEPARATE query. 100 users → 1 + 100 = 101 queries. Looks fine in dev; explodes in prod. Fix: always `.Include()` related data you'll touch. Or use projection: `.Select(u => new { u.Name, PostCount = u.Posts.Count })`.

💡 DbContext is NOT thread-safe

DbContext is designed for short-lived, scoped use. Register as Scoped (per request) in DI. Never share a DbContext across threads (data corruption + EF errors). Never make it a Singleton. Never keep one alive across requests.

Common mistakes

Forgetting Include() → N+1 queries in prod. Singleton DbContext → corrupted state. Loading entire table for a count (use `.CountAsync()` not `.ToListAsync().Count`). Saving inside a loop (call SaveChangesAsync ONCE at the end of a batch).

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←ASP.NET Core REST APIs
Back to C# and .NET
C# for Game Dev: Unity Intro→