The DbContext is the absolute heart of Entity Framework Core. It represents a living session with the database. It is responsible for establishing the network connection, maintaining the Change Tracker, executing SQL, and marshaling data mapped to DbSet properties.
You must inherit from Microsoft's base DbContext class. Every table you want to query must be exposed as a DbSet<TEntity> property.
using Microsoft.EntityFrameworkCore;
public class ApplicationDbContext : DbContext
{
// The constructor accepts connection options from Program.cs
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
// These properties map directly to physical database tables
public DbSet<User> Users { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Order> Orders { get; set; }
}
You should NEVER hardcode connection strings (Passwords, Server IPs) directly into the C# source code. They must be stored in configuration files or Environment Variables.
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=ECommerceDb;User Id=sa;Password=SuperSecret!;TrustServerCertificate=True;"
}
}
var builder = WebApplication.CreateBuilder(args);
// Grab the secure string
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
// Register the DbContext into the Dependency Injection container
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
// Instruct EF Core to use the SQL Server provider package
options.UseSqlServer(connectionString);
});
A fatal junior mistake is attempting to create a single DbContext and keeping it alive for the entire lifespan of the application (Singleton). DbContext is explicitly designed to be short-lived. It accumulates memory in its Change Tracker. If used as a Singleton on a web server, it will track thousands of objects until the server runs out of RAM and crashes with an OutOfMemoryException.
AddDbContext, ASP.NET Core registers it as Scoped by default. This means a brand new DbContext is instantiated for every HTTP Request, executes the logic, and is safely destroyed and garbage collected the second the HTTP Request ends.
Q: "If 10,000 users hit our API simultaneously, `AddDbContext` will frantically instantiate and destroy 10,000 `ApplicationDbContext` objects in memory per second. How do we prevent CPU exhaustion and Garbage Collection locking under extreme loads?"
Architect Answer: "We use `AddDbContextPool`. Instantiating a DbContext is somewhat heavy computationally because it has to initialize internal Dictionaries and state machines. By switching to `builder.Services.AddDbContextPool