IQueryable represents a query that a data source can translate and execute. In EF Core, a DbSet<Recipe> exposes IQueryable, allowing LINQ filters and projections to be composed before an execution method sends the query to the database. section 12.4.2
An EF Core query commonly follows this sequence:
- Start with a DbSet property on the application data context. section 12.4.2
- Add LINQ Where clauses to filter records and Select clauses to project only the needed fields. section 12.4.2
- Call ToListAsync(), ToArrayAsync(), SingleAsync(), or a corresponding synchronous method to generate and execute the database query. section 12.4.2
- Expect unsupported expressions to run in C# after EF Core retrieves the required database fields. section 12.4.2
Filtering and projecting recipes
A query can exclude soft-deleted recipes and create view models directly: _context.Recipes.Where(r => !r.IsDeleted).Select(r => new RecipeSummaryViewModel { Id = r.RecipeId, Name = r.Name }).ToListAsync(). EF Core selects the columns needed for the projection and builds the returned view models. section 12.4.2
Listing 12.7 Loading a list of items using EF Core in RecipeService
public async Task<ICollection<RecipeSummaryViewModel>> GetRecipes()
{
return await _context.Recipes #1
.Where(r => !r.IsDeleted)
.Select(r => new RecipeSummaryViewModel #2
{ #2
Id = r.RecipeId, #2
Name = r.Name, #2
TimeToCook = $"{r.TimeToCook.TotalMinutes}mins" #2
})
.ToListAsync(); #3
}
#1 A query starts from a DbSet property.
#2 EF Core queries only the Recipe columns it needs to map the view model correctly.
#3 Executes the SQL query and creates the final view models
Shows the complete EF Core pattern from DbSet, through filtering and view-model projection, to asynchronous execution. section 12.4.2



