0Pricing
C# Academy · Lesson

DbContext & DbSet Basics

Set up a DbContext, define entities, configure the connection string, and run your first query.

DbContext & DbSet Basics is a free C# Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is Entity Framework Core?

EF Core is the official .NET Object-Relational Mapper (ORM). It maps C# classes (entities) to database tables and lets you query and save data using LINQ — no SQL required for most operations.

Defining an Entity

An entity is a plain C# class whose properties map to database columns. By convention, a property named Id or <TypeName>Id becomes the primary key.

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public decimal Price { get; set; }
    public int Stock { get; set; }
    public DateTime CreatedAt { get; set; }
}

Creating a DbContext

DbContext is the gateway to the database. It holds DbSet<T> properties for each entity and manages the connection, change tracking, and transactions.

using Microsoft.EntityFrameworkCore;

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

    public DbSet<Product> Products => Set<Product>();
    public DbSet<Order>   Orders   => Set<Order>();
}

Registering DbContext with DI

Call AddDbContext in Program.cs to register the context as a Scoped service and configure the database provider.

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("Default")));

// For SQLite (great for development/testing):
// options.UseSqlite("Data Source=app.db");

Basic Queries with DbSet

DbSet<T> exposes LINQ operators. Queries are not executed until enumerated (await ...ToListAsync()). This is called deferred execution.

public class ProductService
{
    private readonly AppDbContext _db;
    public ProductService(AppDbContext db) => _db = db;

    public async Task<List<Product>> GetExpensiveAsync(decimal minPrice)
    {
        return await _db.Products
            .Where(p => p.Price >= minPrice)
            .OrderBy(p => p.Name)
            .ToListAsync();
    }
}

Finding by Primary Key

FindAsync first checks the local change tracker cache before hitting the database. Use it when querying by primary key to avoid redundant round-trips.

var product = await _db.Products.FindAsync(42);
if (product is null)
    throw new KeyNotFoundException("Product not found");

// For complex keys, pass all key values:
var orderLine = await _db.OrderLines.FindAsync(orderId, productId);

Adding New Records

Call Add to queue an entity for insertion, then SaveChangesAsync to commit. EF Core generates the INSERT SQL and populates the auto-generated Id.

var product = new Product
{
    Name = "Mechanical Keyboard",
    Price = 149.99m,
    Stock = 50,
    CreatedAt = DateTime.UtcNow
};

_db.Products.Add(product);
await _db.SaveChangesAsync();

Console.WriteLine(product.Id); // Auto-generated PK

Updating Records

Entities loaded by EF Core are tracked. Modify properties directly and call SaveChangesAsync — EF Core detects changes and generates an optimized UPDATE statement.

var product = await _db.Products.FindAsync(42);
if (product is not null)
{
    product.Price = 129.99m;
    product.Stock -= 1;
    await _db.SaveChangesAsync(); // UPDATE Products SET Price=...
}

Deleting Records

Call Remove to mark an entity for deletion, then SaveChangesAsync. Use ExecuteDeleteAsync (.NET 7+) for bulk deletes without loading entities.

// Delete a tracked entity
_db.Products.Remove(product);
await _db.SaveChangesAsync();

// Bulk delete without loading (EF Core 7+)
await _db.Products
    .Where(p => p.Stock == 0)
    .ExecuteDeleteAsync();

Configuring with Fluent API

Override OnModelCreating to configure entities using the Fluent API — table names, column types, constraints, indexes, and relationships.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>(entity =>
    {
        entity.ToTable("products");
        entity.Property(p => p.Name).IsRequired().HasMaxLength(200);
        entity.Property(p => p.Price).HasColumnType("decimal(18,2)");
        entity.HasIndex(p => p.Name);
    });
}

Real-World: Repository Using DbContext

A typical repository wraps DbContext to centralize data access logic and keep query details out of service classes.

public class ProductRepository : IProductRepository
{
    private readonly AppDbContext _db;
    public ProductRepository(AppDbContext db) => _db = db;

    public async Task<Product?> GetByIdAsync(int id)
        => await _db.Products.AsNoTracking().FirstOrDefaultAsync(p => p.Id == id);

    public async Task<List<Product>> SearchAsync(string query)
        => await _db.Products
            .Where(p => p.Name.Contains(query))
            .AsNoTracking()
            .ToListAsync();
}

Quick Check

What does AsNoTracking() do when querying with EF Core?

Recap: DbContext & DbSet Basics

Key takeaways:

  • DbContext is the session with the database; DbSet<T> represents a table
  • Register with AddDbContext in DI; it is Scoped by default
  • LINQ queries are deferred — execute with ToListAsync, FirstOrDefaultAsync
  • Change tracking enables automatic UPDATE/DELETE via SaveChangesAsync
  • Use AsNoTracking() for read-only queries to boost performance

Frequently asked questions

Is the “DbContext & DbSet Basics” lesson free?

Yes — the full text of “DbContext & DbSet Basics” is free to read here on the web, and the C# Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO.

What will I learn in “DbContext & DbSet Basics”?

Set up a DbContext, define entities, configure the connection string, and run your first query. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “DbContext & DbSet Basics” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. DbContext & DbSet Basics
  2. Migrations & Schema Management
  3. CRUD Operations with EF Core
  4. Relationships: One-to-Many & Many-to-Many
← Back to C# Academy