liveBook · Manning

Cache entry

As explained in Building Web APIs with ASP.NET Core

A cache entry is a stored value associated with a cache key and optional expiration metadata.

A cache entry stores a value under a cache key, optionally with expiration metadata. In a board-game API, it lets repeated requests reuse results instead of querying EF Core every time. section 8.3.3

Implement a cache entry in the controller by following this sequence:

  • Build a distinct cache key from the request parameters, using the request type and its JSON representation. section 8.3.3
  • Call IMemoryCache.TryGetValue<T> to check whether a suitable entry already exists. section 8.3.3
  • Use the cached array when present; otherwise query with EF Core and store the result with a 30-second absolute expiration. section 8.3.3

Board-game GET requests

A filtered request such as a board-game query produces a key from its RequestDTO<BoardGame> type and serialized parameters. Matching later requests retrieve the cached BoardGame[]; different parameters receive different entries. section 8.3.3

Listing 8.6 BoardGamesController’s Get method
[HttpGet(Name = "GetBoardGames")]
[ResponseCache(CacheProfileName = "Any-60")]
public async Task<RestDTO<BoardGame[]>> Get(
    [FromQuery] RequestDTO<BoardGameDTO> input)
{
  _logger.LogInformation(CustomLogEvents.BoardGamesController_Get,
      "Get method started.");
 
var query = _context.BoardGames.AsQueryable();                         #1
if (!string.IsNullOrEmpty(input.FilterQuery))                        #2
query = query.Where(b => b.Name.Contains(input.FilterQuery));
 
var recordCount = await query.CountAsync();                           #3
 
BoardGame[]? result = null;                                            #4
var cacheKey = $"{input.GetType()}-{JsonSerializer.Serialize(input)}";#5
if (!_memoryCache.TryGetValue<BoardGame[]>(cacheKey, out result))     #6
{
query = query                                                  #7
.OrderBy($"{input.SortColumn} {input.SortOrder}")
.Skip(input.PageIndex * input.PageSize)
.Take(input.PageSize);
result = await query.ToArrayAsync();
_memoryCache.Set(cacheKey, result, new TimeSpan(0, 0, 30));
}
 
  return new RestDTO<BoardGame[]>()
  {
Data = result,                                                    #8
    PageIndex = input.PageIndex,
    PageSize = input.PageSize,
    RecordCount = recordCount,
    Links = new List<LinkDTO> {
      new LinkDTO(
        Url.Action(
          null,
          "BoardGames",
          new { input.PageIndex, input.PageSize },
          Request.Scheme)!,
        "self",
        "GET"),
    }
  };
}

Inspect the controller listing to follow cache-key creation, lookup, conditional querying, and entry storage in sequence. section 8.3.3

How Building Web APIs with ASP.NET Core covers it

How deep it goes
Explains key construction, lookup, conditional querying, and 30-second expiration, stopping short of broader cache design.
Examples
Demonstrates entries through filtered BoardGamesController requests, BoardGame[] results, breakpoints, and Listing 8.6.
What it assumes
Assumes a BoardGamesController, EF Core query, request DTO, and injected IMemoryCache; teaches cache-or-query logic directly.
What you can do after
Build it from scratch using IMemoryCache, serialized request parameters, conditional EF Core queries, and absolute expiration.
How it connects
Connects cache entries with cache keys, IMemoryCache, EF Core, JSON serialization, DTOs, and expiration.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Building Web APIs with ASP.NET Core. The section links point to the parts of the book it draws on.