Caching
Cache In ASP.NET Core, we can implement caching using
InMemoryCache
IDistributedCache
Response Caching, depending on the requirement.
Output Caching
Custem Cache with ConcurrentDictionary for thread-safe
lock -> only one thread can enter that critical section at a time
Cache
Caching is a technique used to store frequently accessed data temporarily so that we don't need to fetch the same data from the database or another external service repeatedly. It improves application performance, reduces database load, and decreases API response time.
Types of caching in .NET Core
i) In-Memory Cache — IMemoryCache
tores data in the memory of the application server.
Use case: Product categories, configuration data, reference/master data.
(Single instance)
ii) Distributed Cache — IDistributedCache
Stores data in a shared cache accessible by multiple application instances, commonly Redis or SQL Server.
Use case: Multi-server deployments, shared cached data, session state.
(Multiple instances)
iii) Response Caching
Caches HTTP responses according to HTTP caching headers and applicable client/proxy behavior.
Use case: Public GET endpoints whose responses can safely be reused.
iv)Output Caching
ASP.NET Core output-caching middleware caches HTTP responses on the server according to configured policies.
Use case: Frequently requested, relatively stable API responses.
Practical example: IMemoryCache
Suppose you have a Product API. Every time a client requests the product list, your API queries SQL Server. If the product list rarely changes, you can cache it for five minutes.
Step 1: Register the cache in Program.cs
builder.Services.AddMemoryCache();
builder.Services.AddScoped<IProductService, ProductService>();
Step 2: Implement caching in the service
using Microsoft.Extensions.Caching.Memory;
public class ProductService : IProductService
{
private readonly IMemoryCache _cache;
private readonly AppDbContext _context;
public ProductService(
IMemoryCache cache,
AppDbContext context)
{
_cache = cache;
_context = context;
}
public async Task<List<Product>> GetProductsAsync()
{
return await _cache.GetOrCreateAsync(
"products",
async entry =>
{
entry.AbsoluteExpirationRelativeToNow =
TimeSpan.FromMinutes(5);
return await _context.Products
.AsNoTracking()
.ToListAsync();
}) ?? new List<Product>();
}
}
OutPut Caching
Output caching is a feature in ASP.NET Core that stores the HTTP response generated by an endpoint on the server. When the same request comes again and matches the caching policy, the server can return the cached response instead of executing the endpoint again.
It improves API performance, reduces database calls, and decreases response time. We can configure output caching using middleware and policies.”
Step 1: Register services in Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddOutputCache();
var app = builder.Build();
app.UseOutputCache();
app.MapControllers();
app.Run();
Step 2: Apply caching to an API endpoint
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
[OutputCache(Duration = 60)]
public IActionResult GetProducts()
{
// Normally, fetch products from the database
var products = new[]
{
new { Id = 1, Name = "Laptop" },
new { Id = 2, Name = "Mobile" }
};
return Ok(products);
}
}
Here, Duration = 60 means the output cache can retain the response for 60 seconds.
- First request: the endpoint executes and the response is cached.
- Subsequent matching requests: the cached response can be returned.
- After expiration: the endpoint executes again and a new response can be cached.
or Configure caching using a policy Instead of applying attributes to multiple endpoints, you can define a reusable policy.
builder.Services.AddOutputCache(options =>
{
options.AddPolicy("ProductsPolicy", policy =>
policy.Expire(TimeSpan.FromMinutes(5)));
});
Apply the Policy :
[HttpGet]
[OutputCache(PolicyName = "ProductsPolicy")]
public IActionResult GetProducts()
{
return Ok(_productService.GetProducts());
}
Custem Caching
using System;
using System.Collections.Concurrent;
namespace HelloWorld
{
public class Program
{
public static void Main(string[] args)
{
var cache = new EmployeeCache();
cache.SetEmployee(new Employee {
Id = 101,
Name = "Sudhanshu",
Salary=60000
});
var employee = cache.GetEmployee(101);
Console.WriteLine("Cached Employee-> Name: "+ employee.Name+ "Id :"+ employee.Id);
bool removeEmp = cache.RemoveEmployee(101);
Console.WriteLine(removeEmp);
}
}
public class EmployeeCache{
private readonly ConcurrentDictionary<int, Employee> _cache = new ConcurrentDictionary<int,Employee>();
public Employee GetEmployee(int id){
_cache.TryGetValue(id, out var employee);
return employee;
}
public void SetEmployee(Employee employee){
_cache[employee.Id]= employee;
}
public bool RemoveEmployee(int id){
return _cache.TryRemove(id, out _);
}
}
public class Employee{
public int Id {get; set;}
public string Name {get; set;}
public int Salary {get; set; }
}
}
Comments
Post a Comment