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

Popular posts from this blog