DbContext
The DbContext
class is the primary gateway to interact with your data in Entity Framework Core. It represents a session with the database and allows you to query and save data.
What is DbContext?
DbContext
is a managed wrapper around a data source. It's your central hub for:
- Establishing a connection to the database.
- Tracking changes to entities.
- Executing queries against the database.
- Persisting changes back to the database.
Key Responsibilities of DbContext:
- Connection Management: It holds the connection string and manages the database connection lifecycle.
- Change Tracking: It keeps track of the state of entities (added, modified, deleted, or unchanged) as you interact with them.
- Query Execution: It translates LINQ queries into SQL queries and executes them against the database.
- Unit of Work Pattern: It acts as a unit of work, allowing you to perform multiple operations and then commit them together as a single transaction.
Creating a DbContext
You typically create a class that inherits from DbContext
and then expose DbSet<TEntity>
properties for each entity type you want to query from the database. The DbSet<TEntity>
represents a collection of all entities in the store for a given type. These collections are accessed from a DbContext
instance.
Example:
using Microsoft.EntityFrameworkCore;
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=Blogging;Trusted_Connection=True;");
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
Configuring DbContext Options
The OnConfiguring
method is where you'll typically configure your DbContext
options, such as the database provider and connection string. For more complex configurations, especially in ASP.NET Core applications, you would use dependency injection and configure options in the Startup.cs
or Program.cs
file.
Using Dependency Injection (ASP.NET Core):
In an ASP.NET Core application, you would register your DbContext
in the ConfigureServices
method of your Startup.cs
(or directly in Program.cs
in .NET 6+):
// In Startup.cs (ConfigureServices)
public void ConfigureServices(IServiceCollection services)
{
var connectionString = "Server=(localdb)\\mssqllocaldb;Database=Blogging;Trusted_Connection=True;";
services.AddDbContext<BloggingContext>(options =>
options.UseSqlServer(connectionString));
// ... other services
}
Then, you can inject DbContext
instances into your controllers or other services.
Working with DbContext Instances
Once you have a DbContext
instance, you can use its DbSet<TEntity>
properties to query and manipulate data.
Querying Data:
using (var context = new BloggingContext())
{
var blogs = context.Blogs.ToList(); // Fetch all blogs
var specificBlog = context.Blogs.Where(b => b.Url.Contains("example.com")).FirstOrDefault(); // Find a specific blog
}
Adding New Entities:
var newBlog = new Blog { Url = "http://newblog.com" };
using (var context = new BloggingContext())
{
context.Blogs.Add(newBlog);
context.SaveChanges(); // Persist the new blog to the database
}
Modifying Entities:
using (var context = new BloggingContext())
{
var blogToUpdate = context.Blogs.Find(1); // Find blog with ID 1
if (blogToUpdate != null)
{
blogToUpdate.Url = "http://updatedblog.com";
context.SaveChanges(); // Save changes
}
}
Deleting Entities:
using (var context = new BloggingContext())
{
var blogToDelete = context.Blogs.Find(2); // Find blog with ID 2
if (blogToDelete != null)
{
context.Blogs.Remove(blogToDelete);
context.SaveChanges(); // Delete from database
}
}
DbContext Lifetime and Disposal
DbContext
instances are designed to be short-lived. They should be created, used for a single unit of work, and then disposed of. This is crucial for managing database connections efficiently and preventing memory leaks. Using a using
statement ensures that the DbContext
is properly disposed of.
A well-designed
DbContext
implementation is fundamental to leveraging the power of Entity Framework Core for efficient and robust data access.