Entity Framework Core Basic Querying
This document covers the fundamental ways to query data using Entity Framework Core (EF Core). EF Core provides a powerful and intuitive API for retrieving data from your database.
Introduction to Querying
EF Core's querying capabilities are built around the concept of LINQ (Language Integrated Query). LINQ allows you to write queries in C# or Visual Basic that are translated into SQL by EF Core.
The DbSet<TEntity>
Property
Your EF Core DbContext
class typically exposes properties of type DbSet<TEntity>
. Each DbSet
represents a collection of entities of a specific type in your database and serves as the entry point for querying.
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
// ... other DbContext configurations
}
Basic Query Operations
Retrieving All Entities
To retrieve all entities of a given type, you can simply access the DbSet
.
using (var context = new BloggingContext())
{
var allBlogs = context.Blogs.ToList(); // Executes a query to fetch all blogs
}
The ToList()
method executes the query and materializes the results into a List<Blog>
.
Filtering Data (Where
)
The Where
extension method is used to filter results based on a predicate.
using (var context = new BloggingContext())
{
var techBlogs = context.Blogs
.Where(b => b.Name.Contains("Technology"))
.ToList();
}
Selecting Specific Properties (Select
)
The Select
method allows you to project the results into a new shape, often selecting only specific properties.
using (var context = new BloggingContext())
{
var blogNames = context.Blogs
.Select(b => b.Name)
.ToList(); // Returns a List<string>
}
Ordering Results (OrderBy
and OrderByDescending
)
You can sort the results using OrderBy
and OrderByDescending
.
using (var context = new BloggingContext())
{
var sortedBlogs = context.Blogs
.OrderBy(b => b.Rating)
.ToList();
var reverseSortedBlogs = context.Blogs
.OrderByDescending(b => b.CreationDate)
.ToList();
}
Taking a Specific Number of Results (Take
)
The Take
method limits the number of results returned.
using (var context = new BloggingContext())
{
var firstFiveBlogs = context.Blogs
.OrderBy(b => b.Rating)
.Take(5)
.ToList();
}
Skipping Results (Skip
)
The Skip
method allows you to skip a specified number of results, often used for pagination.
using (var context = new BloggingContext())
{
int pageSize = 10;
int pageNumber = 2;
var pageOfBlogs = context.Blogs
.OrderBy(b => b.Name)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
}
Counting Results (Count
)
The Count()
method can be used to get the number of entities that satisfy a condition.
using (var context = new BloggingContext())
{
int numberOfTechBlogs = context.Blogs
.Count(b => b.Name.Contains("Technology"));
}
Query Execution
EF Core uses lazy loading by default. This means that database queries are generally only executed when the data is actually needed (e.g., when you iterate over a collection or call a method like ToList()
).
Note on Query Execution
Understanding when queries are executed is crucial for performance. Excessive calls to ToList()
can lead to fetching more data than necessary.
Including Related Data (Navigation Properties)
EF Core allows you to easily load related data through navigation properties using the Include
method. This avoids the need for separate queries to load related entities.
Example: Including Posts for each Blog
using (var context = new BloggingContext())
{
var blogsWithPosts = context.Blogs
.Include(b => b.Posts) // Load related Posts
.ToList();
foreach (var blog in blogsWithPosts)
{
Console.WriteLine($"Blog: {blog.Name}");
foreach (var post in blog.Posts)
{
Console.WriteLine($"- Post: {post.Title}");
}
}
}
In this example, the query will fetch blogs and their associated posts in a single database roundtrip. If your models have complex relationships, you can chain Include
calls.
LINQ to Entities vs. LINQ to Objects
It's important to distinguish between LINQ to Entities (queries executed against the database) and LINQ to Objects (queries executed against in-memory collections).
Tip
Always aim to perform filtering, sorting, and projection operations on the database side (using LINQ to Entities) whenever possible. This is generally more efficient than fetching all data into memory and then processing it.
Next Steps
Continue to the Advanced Querying section to explore more complex query scenarios, including filtering on related data, projections, and the use of the AsNoTracking()
method for performance optimization.