What is Caching?
Caching is process of storing frequently accessed data, files, content or resources in a temporary storage location, so that they can be quickly retrieved and served to users upon request, without having to be regenerated or fetched from the original source.
Caching is commonly used to improve the performance of web applications to load data, file or content as soon as possible to reduce the request to server again and again.
Azure Cache for Redis
Azure Cache for Redis provides an in-memory data store based on the Redis software. Redis improves the performance and scalability of an application that uses backend data stores heavily. It’s able to process large volumes of application requests by keeping frequently accessed data in the server memory, which can be written to and read from quickly. Redis brings a critical low-latency and high-throughput data storage solution to modern applications.
Connect an app to Azure Cache for Redis by using .NET Core
1. Create an Azure Cache for Redis instance in your Azure portal.
2. Create .Net 6 api in Visual Studio 2022
3. Install Microsoft.Extensions.Caching.StackExchangeRedis nugget to use Redis.
4. Add below code in Program.cs class.
builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = "your-redis-cache-connection-string"; });
5. Replace "your-redis-cache-connection-string"
with the connection string for your Azure Cache for Redis instance.
6. Create an Interface IRedisCacheService and paste below code.
using Microsoft.Extensions.Caching.Distributed; namespace Azure_Cache_for_Redis.Repository.Interfaces { public interface IRedisCacheService { Task<T> GetAsync<T>(string key); Task SetAsync<T>(string key, T value, DistributedCacheEntryOptions options = null); Task RemoveAsync(string key); } }
7. Create a ProductService.cs Class and paste below code.
using Azure_Cache_for_Redis.DA; using Azure_Cache_for_Redis.Models; using Azure_Cache_for_Redis.Repository.Interfaces; using Microsoft.EntityFrameworkCore; namespace Azure_Cache_for_Redis.Repository.Services { public class ProductService : IProductService { private readonly DataContext _dataContext; public ProductService(DataContext dataContext) { _dataContext = dataContext; } public async Task<int> AddProduct(Product product) { _dataContext.Products.Add(product); await _dataContext.SaveChangesAsync(); return product.Id; } public async Task<Product> GetProducts(int id) { return await _dataContext.Products.Where(x => x.Id == id).FirstOrDefaultAsync(); } } }
8. Create Product.cs class in Model folder.
namespace Azure_Cache_for_Redis.Models { public class Product { public int Id { get; set; } public string? Name { get; set; } public string? Colour { get; set; } public string? Type { get; set; } public decimal Price { get; set; } } }
9. Create DataContext.cs class and paste below code to use EF Core.
using Azure_Cache_for_Redis.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; namespace Azure_Cache_for_Redis.DA { public class DataContext : DbContext { public DataContext(DbContextOptions<DataContext> options) : base(options) { } public DbSet<Product> Products { get; set; } } }
10. Paste below code in Program.cs to ineject service to use SqlServer.
builder.Services.AddDbContext<DataContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("AzureRedisApp")); });
11. Install following nugget packages for EF core and add migration.
- NuGet\Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 6.0.14
- NuGet\Install-Package Microsoft.EntityFrameworkCore.Design -Version 6.0.14
- NuGet\Install-Package Microsoft.EntityFrameworkCore.Tool-Version 6.0.14
12. Paste your connection string in appsetting.json.
"ConnectionStrings": { "AzureRedisApp": "Data Source=.;Initial Catalog=RedisDB;Integrated Security=SSPI;" },
13. Run following migration in package console to create table in your database.
- add-migratin initial-create
- update-database
14. Create an IProductService interface and paste below code.
using Azure_Cache_for_Redis.Models; namespace Azure_Cache_for_Redis.Repository.Interfaces { public interface IProductService { public Task<int> AddProduct(Product product); public Task<Product> GetProducts(int id); } }
15. Create a class ProductService.cs and paste below code.
using Azure_Cache_for_Redis.DA; using Azure_Cache_for_Redis.Models; using Azure_Cache_for_Redis.Repository.Interfaces; using Microsoft.EntityFrameworkCore; namespace Azure_Cache_for_Redis.Repository.Services { public class ProductService : IProductService { private readonly DataContext _dataContext; public ProductService(DataContext dataContext) { _dataContext = dataContext; } public async Task<int> AddProduct(Product product) { _dataContext.Products.Add(product); await _dataContext.SaveChangesAsync(); return product.Id; } public async Task<Product> GetProducts(int id) { return await _dataContext.Products.Where(x => x.Id == id).FirstOrDefaultAsync(); } } }
16. Last and final step to create a Controller and paste below code.
using Azure_Cache_for_Redis.Models; using Azure_Cache_for_Redis.Repository.Interfaces; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Distributed; using System.Xml.Linq; namespace Azure_Cache_for_Redis.Controllers { [Route("api/[controller]")] [ApiController] public class ProductController : Controller { private readonly IRedisCacheService _cacheService; private readonly IProductService _productService; public ProductController(IRedisCacheService cacheService, IProductService productService) { _cacheService = cacheService; _productService = productService; } [HttpPost] public async Task<ActionResult> AddProduct(Product product) { int id = await _productService.AddProduct(product); if (id != null) return Ok(id); else return BadRequest(); } [HttpGet] public async Task<IActionResult> GetProductById(int id) { try { var cacheKey = $"mydata_{id}"; var cachedData = await _cacheService.GetAsync<Product>(cacheKey); if (cachedData != null) { // data is in cache, use it return Ok(cachedData); } //data is not in cache, fetch it from database var data = await _productService.GetProducts(id); //store data in cache await _cacheService.SetAsync(cacheKey, data, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10) }); return Ok(data); } catch (Exception ex) { throw; } } } }
17. Test with Postman first when data come from MSSQL.
18. Second Time when data come from cache.
Note: You See how data come fast from Cache.