100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
C#

DbContext and DbSet

How DbContext and DbSet work together as EF Core's session and table-collection abstractions, including change tracking and fluent configuration.

FoundationsBeginner8 min readJul 10, 2026
Analogies

DbContext and DbSet

DbContext is the primary class you use to interact with a database in EF Core; it represents a session with the database and combines the Unit of Work and Repository patterns. DbSet<TEntity> properties on your DbContext represent collections of entities that map to tables you can query and persist.

🏏

Cricket analogy: A DbContext is like a match day squad sheet for a team such as Mumbai Indians — one session object holding separate lists (DbSets) for batsmen, bowlers, and support staff, all tracked together for that game.

Defining a DbContext

You create a DbContext by subclassing DbContext, exposing DbSet<T> properties for each entity type, and passing configuration through its constructor (or overriding OnConfiguring) so the context knows which provider and connection to use.

🏏

Cricket analogy: Like a franchise creating its own team roster class extending a generic 'Squad' template with named slots for Batsmen and Bowlers, you subclass DbContext and add named DbSet<T> properties for each entity.

DbSet and Change Tracking

Each DbSet<TEntity> is backed by EF Core's change tracker, which monitors entity state (Added, Modified, Deleted, Unchanged) so that when SaveChanges() runs, EF Core knows exactly which INSERT, UPDATE, or DELETE statements to generate.

🏏

Cricket analogy: Like a scorer marking each player's status for the innings — 'Not Out', 'Retired Hurt', 'New Batsman In' — EF Core's change tracker tags each entity as Unchanged, Modified, or Added so SaveChanges knows what to do.

Configuring Entities with the Fluent API

Beyond DbSet declarations, you can override OnModelCreating to configure keys, relationships, and constraints via the fluent API on ModelBuilder, giving fine-grained control beyond what data annotations alone can express.

🏏

Cricket analogy: Like a coach fine-tuning a generic training plan with specific instructions for a player such as Jasprit Bumrah's bowling workload, the fluent API in OnModelCreating lets you fine-tune entity configuration beyond default conventions.

csharp
public class BookStoreContext : DbContext
{
    public BookStoreContext(DbContextOptions<BookStoreContext> options) : base(options) { }

    public DbSet<Book> Books => Set<Book>();
    public DbSet<Author> Authors => Set<Author>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Book>()
            .HasOne(b => b.Author)
            .WithMany(a => a.Books)
            .HasForeignKey(b => b.AuthorId);

        modelBuilder.Entity<Book>()
            .Property(b => b.Title)
            .IsRequired()
            .HasMaxLength(200);
    }
}

DbContext instances are lightweight and cheap to create but are NOT thread-safe — never share one DbContext instance across concurrent operations or parallel tasks; request a new scoped instance instead.

  • DbContext represents a session with the database and tracks entity state.
  • DbSet<TEntity> properties expose queryable, persistable collections mapped to tables.
  • You subclass DbContext and typically inject DbContextOptions via its constructor.
  • The change tracker marks entities as Added, Modified, Deleted, or Unchanged.
  • OnModelCreating and the fluent API (ModelBuilder) configure keys, relationships, and constraints.
  • DbContext instances are not thread-safe and should not be shared across concurrent operations.

Practice what you learned

Was this page helpful?

Topics covered

#EntityFrameworkCoreStudyNotes#MicrosoftTechnologies#DbContextAndDbSet#DbContext#DbSet#Defining#Change#StudyNotes#SkillVeris#ExamPrep