.NET 7 💥 — Web API In-Memory Caching ⏲🌐
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