liveBook · Manning

IQueryable

As explained in .NET in Action, Second Edition

IQueryable is a LINQ interface representing a queryable data source whose query expression can be interpreted by a provider.

IQueryable is a LINQ-specific interface that extends IEnumerable. In EF Core, it gives a query over a DbSet a type that can be modified as filtering, ordering, or paging requirements become known. section 5.2 section 5.4.1

Common LINQ operations serve different jobs:

  • Where filters; Select projects; OrderBy and OrderByDescending sort. section 5.2
  • Skip and Take page results; FirstOrDefault retrieves an element matching a condition. section 5.2 section 5.4.1
  • ToList, ToArray, and ToDictionary convert a query to a collection. Conversion materializes it, retrieving all its entities. section 5.2

Save before querying

Add Book objects to a CatalogContext, call SaveChanges(), then iterate dbContext.Books.OrderBy(b => b.Id). Moving SaveChanges() after the query leaves no books to retrieve: the DbSet accesses database contents, not additions still held only in code. section 5.2

Listing 5.25 Adding a new controller that allows requesting a list of books
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
  
namespace ManningBooksApi.Controllers;                 #1
  
[ApiController]                                        #2
[Route("[controller]")]                                #3
public class CatalogController : ControllerBase
{
  private readonly CatalogContext _dbContext;          #4
  
  public CatalogController(
    CatalogContext dbContext)                          #5
  {
    _dbContext = dbContext;
  }
  
  [HttpGet]                                            #6
  public IAsyncEnumerable<Book> GetBooks(              #7
      string? titleFilter = null)                      #8
  {
    IQueryable<Book> query = _dbContext.Books          #9
      .Include(b => b.Ratings)
      .AsNoTracking();                                 #10
    if (titleFilter != null)
    {
      query = query.Where(b =>
        b.Title.ToLower().Contains(titleFilter.ToLower()));
    }
  
    return query.AsAsyncEnumerable();                  #11
  }
}

The GET action starts with an IQueryable<Book> from the Books DbSet and applies Include and AsNoTracking. Keeping the value queryable allows the action to modify it for request options; an accompanying exercise adds sorting and paging parameters. section 5.4.1

How .NET in Action, Second Edition covers it

How deep it goes
Defines IQueryable through IEnumerable and demonstrates DbSet queries, but does not explain provider internals.
Examples
Shows an ordered Book query after SaveChanges() and a catalog GET action initialized with IQueryable<Book>.
What it assumes
Builds on C# collections and DbContext usage while defining IEnumerable and IQueryable before using LINQ operations.
What you can do after
Apply it via EF Core to compose catalog queries and add request-controlled sorting and paging.
How it connects
Connects IQueryable to IEnumerable, LINQ extensions, DbSet, materialization, and ASP.NET Core request methods.

Also explained in

Compare how 4 books explain IQueryable →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of .NET in Action, Second Edition. The section links point to the parts of the book it draws on.