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 PKUpdating 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
AddDbContextin 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.