Open to work
Published on

Implementation of .NET Core API In Memory Caching in CRUD operations using separate service

Authors

Add NuGet Package

To enable in-memory caching, we need to add the Microsoft.Extensions.Caching.Memory NuGet package from package manager console.

Install-Package Microsoft.Extensions.Caching.Memory

Configuring In-Memory caching in existing application

In the Program.cs file of your project, configure the in-memory cache service in the ConfigureServices method:

using Microsoft.Extensions.Caching.Memory;

public void ConfigureServices(IServiceCollection services)
{
    // Add memory cache service
    services.AddMemoryCache();
}

Creating a Cache Service

Here is the asynchronous ICacheService implementations

    public interface ICacheService
    {
        Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> getItemCallback, TimeSpan expirationTime);
        Task CreateOrUpdateAsync<T>(string key, T newItem, TimeSpan expirationTime);
        Task DeleteAsync(string key);
    }

Now declations of ICacheService in CacheService implementations

public class CacheService : ICacheService
    {
        private readonly IMemoryCache _memoryCache;

        public CacheService(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }

        public async Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> getItemCallback, TimeSpan expirationTime)
        {
            if (_memoryCache.TryGetValue(key, out T cachedItem))
            {
                return cachedItem;
            }

            T item = await getItemCallback();

            if (item != null)
            {
                _memoryCache.Set(key, item, expirationTime);
            }

            return item;
        }

        public async Task CreateOrUpdateAsync<T>(string key, T newItem, TimeSpan expirationTime)
        {
            _memoryCache.Set(key, newItem, expirationTime);
            await Task.Yield(); // Async operation to match the method signature.
        }

        public async Task DeleteAsync(string key)
        {
            _memoryCache.Remove(key);
            await Task.Yield(); // Async operation to match the method signature.
        }

    }

Using In-Memory caching in Controller with CRUD

GetAll

        [HttpGet]
        public async Task<IActionResult> GetAllPosts()
        {
            // This method will determine whether your data will serve from the cache or database
            var cachedPosts = await _cacheService.GetOrSetAsync(
                    "all_posts", //cache key
                     () => _postService.GetAllPostsAsync(), //collection of data from database
                    TimeSpan.FromMinutes(10) // Expiration of cache
                        );

            if (cachedPosts == null || !cachedPosts.Any())
            {
                return NotFound("No posts found.");
            }

            return Ok(cachedPosts);
        }

For GetById

            var cachedPost = await _cacheService.GetOrSetAsync(
                    $"post_{postId}", // cache key
                    () => _postService.GetPostByIdAsync(postId),
                    TimeSpan.FromMinutes(10)
                );

            if (cachedPost == null)
            {
                return NotFound($"Post with ID {postId} not found.");
            }

            return Ok(cachedPost);

As all caching depends on cache key, here we have added cache key by id $"post_{postId}".

Create Or Update

await _cacheService.CreateOrUpdateAsync($"post{post.Id}", post, TimeSpan.FromMinutes(10));

we need to provide same cache key to create and update cache when creating or updating data.

Delete

await _cacheService.DeleteAsync($"post{postId}");

GitHub repo for this implementation https://github.com/rabbyalone/PersonalBlogAPI