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
