Reputation: 2375
I have a cacheHelper. When I add the dependency of CacheHelper to startup with "AddScoped", it is working. But,CacheHelper.cs
is running for every request. So, I convert to "AddSingleton" like below. But I'm taking an error, like that:
Cannot consume scoped service 'MyProject.DataAccess.IUnitOfWork' from singleton 'MyProject.Caching.ICacheHelper' How can I fix this problem?
Strartup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped<IJwtHelper, JwtHelper>();
services.AddScoped<IAuditHelper, AuditHelper>();
services.TryAdd(ServiceDescriptor.Singleton<IMemoryCache, MemoryCache>());
services.AddSingleton<ICacheHelper, CacheHelper>();
services.AddMvc();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
CacheHelper.cs
public class CacheHelper : ICacheHelper
{
private readonly IUnitOfWork unitOfWork;
public IMemoryCache Cache { get; }
public CacheHelper(IUnitOfWork unitOfWork, IMemoryCache cache)
{
this.unitOfWork = unitOfWork;
Cache = cache;
}
public void SetCommonCacheItems()
{
var cities = unitOfWork.CityRepo.GetAll();
Cache.Set("cities", cities);
string obj;
Cache.TryGetValue<string>("cities", out obj);
}
public string GetCities()
{
string obj;
Cache.TryGetValue<string>("cities", out obj);
return obj;
}
}
Upvotes: 2
Views: 2787
Reputation: 64150
The way you had it before was the correct one. ICacheHelper
should and have to be scoped.
Just your cache implementation is wrong. Get cities will be called, it checks the cache. If not found, it will get the data and put it into the cache.
public class CacheHelper : ICacheHelper
{
private readonly IUnitOfWork unitOfWork;
public IMemoryCache Cache { get; }
public CacheHelper(IUnitOfWork unitOfWork, IMemoryCache cache)
{
this.unitOfWork = unitOfWork;
Cache = cache;
}
public string GetCities()
{
if(!Cache.TryGetValue<string>("cities", string out cities))
{
// not found in cache, obtain it
cities = unitOfWork.CityRepo.GetAll();
Cache.Set("cities", cities);
}
return cities;
}
}
You don't need SetCommonCacheItems()
method. The important thing is that IMemoryCache
is static, since it will contain the data. UoW has to be scoped, because of the database, otherwise you would have memory leaks (especially when using EF Core, since its caching/tracking the entities).
Upvotes: 2