.NET 7 💥 — Web API In-Memory Caching ⏲🌐

Mohamad Talal Lawand
4 min readFeb 21, 2023

In this article we will be discussing, In-Memory caching with .NET Web API.

You can watch the full video on Youtube

First we will be focusing on installing PostgreSQL on our machine.

Installing Postgres on your machine

brew install postgresql

Starting and Stoping Postgres is running

brew services start postgresql
brew services stop postgresql

Connect with Postgres

psql postgres

Create User and Pass so we can utilise them in our .NET app

CREATE ROLE mohamad WITH LOGIN PASSWORD '12345678';
ALTER ROLE mohamad CREATEDB;
ALTER ROLE mohamad WITH Superuser;

Create a Database

create database sampledb;

Grand permission to the db

GRANT CONNECT ON DATABASE sampledb TO mohamad;

Installing EF tool

dotnet tool install --global dotnet-ef

The first step is we need to create our webapi

dotnet new webapi -n "ApiCaching"

Now we need to add packages so we can utilise our PostgreSQL and EF core

dotnet add package Microsoft.EntityFrameworkCore 
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package System.Runtime.Caching

Now it’s time to add the models, for this sample application we will be creating an app to list all F1 drivers. For this we will create a Models folder in the root directory of our application which will contain our models

Inside the Models folder we will create a new class called Driver

namespace ApiCaching.Models;

public class Driver
{
public int Id { get; set; }
public string Name { get; set; } = "";
public int DriverNumber { get; set; }
public string Team { get; set; } = "";
}

After the model has been created the next step is to create our database db context in the root directory of our application we will create a new folder called Data and inside the Data folder will add the AppDbContext class

using ApiCaching.Models;
using Microsoft.EntityFrameworkCore;

namespace ApiCaching.Data;

public class AppDbContext: DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options): base(options) { }

public DbSet<Driver> Drivers { get; set; }
}

Now we need to add the connection string in the appsettings.json

"ConnectionStrings": {
"SampleDbConnection": "User ID =mohamad;Password=12345678;Server=localhost;Port=5432;Database=sampledb1; Integrated Security=true;Pooling=true;",
}

Next we need to update our program.cs

builder.Services.AddEntityFrameworkNpgsql().AddDbContext<AppDbContext>(opt =>
opt.UseNpgsql(builder.Configuration.GetConnectionString("SampleDbConnection")));

Once we add these we can do our migration

dotnet ef migrations add "initial_migration"
dotnet ef database update

Now, we are going to create ICacheService Interface and CacheService Class for our cache service.

In the root directory of our application we need to create an folder called services and inside the folder we need to create the following

ICacheService

namespace ApiCaching.Services;

public interface ICacheService
{
T GetData<T>(string key);

bool SetData<T>(string key, T value, DateTimeOffset expirationTime);

object RemoveData(string key);
}

CacheService

using System.Runtime.Caching;

namespace ApiCaching.Services;

public class CacheService : ICacheService
{
private ObjectCache _memoryCache = MemoryCache.Default;


public T GetData<T>(string key)
{
try
{
T item = (T)_memoryCache.Get(key);

return item;
}
catch (Exception e)
{
throw;
}
}

public bool SetData<T>(string key, T value, DateTimeOffset expirationTime)
{
var res = true;
try
{
if (!string.IsNullOrEmpty(key))
_memoryCache.Set(key, value, expirationTime);

else
res = false;

return res;
}
catch (Exception e)
{
throw;
}
}
public object RemoveData(string key)
{
var res = true;
try
{
if (!string.IsNullOrEmpty(key))
{
var result = _memoryCache.Remove(key);
}
else
res = false;
}
catch(Exception e)
{
throw;
}
return res;
}
}

Now we need to register our CacheService in our program.cs

builder.Services.AddScoped<ICacheService, CacheService>();

Now let us add the controllers inside the Controllers folder we need to create DriversController class

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ApiCaching.Data;
using ApiCaching.Models;
using ApiCaching.Services;

namespace ApiCaching.Controllers;

[ApiController]
[Route("[controller]")]
public class DriversController : ControllerBase
{
private readonly ILogger<DriversController> _logger;
private readonly AppDbContext _dbContext;
private readonly ICacheService _cacheService;

public DriversController(
ILogger<DriversController> logger,
AppDbContext dbContext,
ICacheService cacheService)
{
_logger = logger;
_dbContext = dbContext;
_cacheService = cacheService;
}

[HttpGet("drivers")]
public async Task<IActionResult> Get()
{
_logger.LogInformation("123 - hi");

var cacheData = _cacheService.GetData<IEnumerable<Driver>>("drivers");

if (cacheData != null && cacheData.Count() > 0)
return Ok(cacheData);

var expirationTime = DateTimeOffset.Now.AddMinutes(5.0);

cacheData = await _dbContext.Drivers.ToListAsync();

_cacheService.SetData<IEnumerable<Driver>>("drivers", cacheData, expirationTime);

_logger.LogInformation("Using db");
return Ok(cacheData);
}

[HttpPost("addDriver")]
public async Task<IActionResult> Post(Driver value)
{
var obj = await _dbContext.Drivers.AddAsync(value);

_cacheService.RemoveData("driver"+ value.Id);

await _dbContext.SaveChangesAsync();

return Ok(obj.Entity);
}

[HttpPut("updatedriver")]
public async Task<IActionResult> Put(Driver driver)
{
_dbContext.Drivers.Update(driver);
_cacheService.RemoveData("driver" + driver.Id);
_dbContext.SaveChanges();

return NoContent();
}

[HttpDelete("deletedriver")]
public async Task<IActionResult> Delete(int Id)
{
var filteredData = _dbContext.Drivers.FirstOrDefault(x => x.Id == Id);
_dbContext.Remove(filteredData);
_cacheService.RemoveData("driver"+ Id);
await _dbContext.SaveChangesAsync();

return NoContent();
}

[HttpGet("driver")]
public async Task<IActionResult> Get(int id)
{
Driver filteredData;
var cacheData = _cacheService.GetData<Driver>("driver"+ id);
if (cacheData != null)
{
return Ok(cacheData);
}
filteredData = _dbContext.Drivers.FirstOrDefault(x => x.Id == id);

var expirationTime = DateTimeOffset.Now.AddMinutes(5.0);

_cacheService.SetData<Driver>("driver"+id, filteredData, expirationTime);

return Ok(filteredData);
}
}

Please post your questions below

--

--

Mohamad Talal Lawand

A determined and forward-thinking Technical Architect with 14+ years of experience.