I have an ASP.NET core application and I am attempting to use Redis Cache - however I am getting an Error saying cannot access a disposed object so I must not have set up my Cache classes correctly. I have pulled the Cache service classes into my own Nuget repository so it can be used by other applications passing in a different Db Number from appsettings.json in other applications
I am using inbuilt .NET Core DI to register the cache service as below:
services.AddTransient<ICacheService, CacheService>();
The cache service is used in my Application then as so:
var dataFromCache = _cacheService.TryGetCachedObject<List<MyObject>>(cacheKey);
The implentation of my Cache service in the nuget pacakge is below:
public class CacheService : ICacheService, IDisposable
{
public virtual T TryGetCachedObject<T>(string cacheKey)
{
if (RedisCacheHandler.Cache.KeyExists(cacheKey))
{
return JsonConvert.DeserializeObject<T>(RedisCacheHandler.Cache.StringGet(cacheKey));
}
return default(T);
}
//other metjhods omitted for brevity
I get the cannot access disposed object exception on the line if (RedisCacheHandler.Cache.KeyExists(cacheKey))
My redis cache handler class is below (the commented out lines if things I have been trying with no success.
public static class RedisCacheHandler
{
private static Lazy<ConnectionMultiplexer> _lazyConnection;
private static ConnectionMultiplexer Connection => _lazyConnection.Value;
//private static CacheSettings _cacheSettings;
public static IDatabase Cache { get; set; }
//public static IDatabase Cache => Connection.GetDatabase(Convert.ToInt32(_cacheSettings.DbNumber));
//private static readonly Lazy<ConnectionMultiplexer> LazyConnection
// = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(_cacheSettings.Connection));
//public static ConnectionMultiplexer Connection => LazyConnection.Value;
public static void AddRedisCacheHandler(this IServiceCollection services, IConfiguration configuration)
{
var cacheSettings = new CacheSettings();
configuration.Bind("CacheSettings", cacheSettings);
//_cacheSettings = cacheSettings;
_lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(cacheSettings.Connection));
Cache = Connection.GetDatabase(Convert.ToInt32(cacheSettings.DbNumber));
}
}
And I was calling the AddRedisCacheHandler method in asp.net core startup class in the ConfigureServices method as below:
services.AddRedisCacheHandler(Configuration);
EDIT
The usage of this is that I hit an API controller to go get reference data. The API controller calls to the Service Layer which then will check if the data is in cache and retrieve from there else will go get data from DB and set it in the cache for 24 hours
private readonly IMyService _myService
public MyController(IMyService myService)
{
_myService = myService;
}
[Route("SomeReferenceData")]
public IEnumerable<SomeDto> GetReferenceData()
{
var data = _myService.GetRefData();
//do stuff and return
}
At the service layer then the code is:
public class MyService : IMyService
{
private readonly ICacheService _cacheService;
private readonly CacheSettings _cacheSettings;
public MyService(CacheSettings cacheSettings, ICacheService cacheService)
{
_cacheSettings = cacheSettings;
_cacheService = cacheService;
}
public virtual IEnumerable<MyObject> GetRefData()
{
string cacheKey = CachingConstants.CacheKey;
var data = _cacheService.TryGetCachedObject<List<MyObject>>(cacheKey);
if (data != null)
{
return data;
}
//go get data from db
_cacheService.SetCachedObject<IEnumerable<MyObject>>(cacheKey, countries, Convert.ToInt32(_cacheSettings.DurationLongMinutes));
return data;
}
From startup I am calling the below to Register all the dependencies including the cache service:
services.RegisterServiceDependencies();
public static class ServiceConfig
{
public static void RegisterServiceDependencies(this IServiceCollection services)
{
services.AddTransient<ICacheService, CacheService>();
//lots of other services