0

I am building a online shop website. I want to display ProductCategory as a Sidebar (short list categories, Eg Clothes, Electronics, Furniture, Books, etc).

At the end, I want to send around productcategory _cache variable to all controllers.Does this methodology seem correct? Additionally, how do I remove unnecessary memorycache parameter in Home Controller? Make a method in Scheduled stuff to retrieve it?

DI Solution:

public class HomeController : Controller
{    
   private readonly IMemoryCache _cache;
   public IScheduledStuff _scheduledstuff;
   public HomeController(IMemoryCache cache, IScheduledStuff scheduledstuff)
   {
        _cache = cache;
        _scheduledstuff = scheduledstuff;
        _scheduledstuff.ScheduleItemsExecute();
    }
    public IActionResult Index()
    {
        ViewBag.ProductCategoryList = _cache.Get<IEnumerable<ProductCategory>>("Teststore");
        return View();
    }
}

public class ProductCategoryRepository : IProductCategoryRepository<ProductCategory>
{
    public IEnumerable<ProductCategory> GetAllProductCategory()
    {
        return _context.ProductCategory.ToList();
    }
}

public ProductCategory()
{
    public int ProductCategoryId { get; set; }
    public string ProductCategoryName { get; set; }
    public string ProductCategoryDescription { get; set; }
}

public class ScheduledStuff : IScheduledStuff
{
    private readonly DatabaseContext _context;
    IMemoryCache MemCache;
    public IProductCategoryRepository<ProductCategory> productcategoryrepository;

    public ScheduledStuff(DatabaseContext context, IMemoryCache memCache)
    {
        _context = context;
        MemCache = memCache;
        productcategoryrepository = new ProductCategoryRepository(_context);
    }

    public void ScheduleItemsExecute()
    {
        var testdata = productcategoryrepository.GetAllProductCategory();
        MemCache.Set("Teststore", testdata);
    }
}


public class Startup
{
    public IProductCategoryRepository<ProductCategory> productcategoryrepository;
    public IMemoryCache memorycache;

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddSingleton<ScheduledStuff>();

Asp.Net Core: Use memory cache outside controller

Solution Static: Keep receiving Null exception error, can someone help fix this?

public static class MemoryCacheStatic
{
    public static IMemoryCache MemCacheStatic;
    public static IProductCategoryRepository<ProductCategory> productcategoryrepositorystatic;

    // Error on this line: <--- NullReferenceException: Object reference not set to an instance of an object.
    public static IEnumerable<ProductCategory> ProductCategoryStatic = productcategoryrepositorystatic.GetAllProductCategory();   


     public static void SetValues()
     {
        ProductCategoryStatic = productcategoryrepositorystatic.GetAllProductCategory();
        MemCacheStatic.Set("Teststore", ProductCategoryStatic) ;
     }
13
  • Another Solution: However, this does not seem right. could you explain ? Commented Sep 29, 2018 at 20:51
  • well, it seem I have a lot of lists to load (5+), should I just place them all in ConfigureServices, or make them global? Commented Sep 29, 2018 at 21:06
  • 1
    AspNet Core is build around DI, you already use constructor injection. That is all you need. And your code sample is totally invalid, non compiling. Makes it hard to understand your problem. Just use services.AddMemoryCache(); Commented Sep 29, 2018 at 21:21
  • thats another thing, trying to get the configure services to compile, still working on it, just want to make sure I am on correct path, so you are recommending configureservices path I assume Commented Sep 29, 2018 at 21:24
  • You can't declare public fields/properties inside a method. And yes, go with the flow. Less work, less errors. Commented Sep 29, 2018 at 21:25

3 Answers 3

1

This should work, thanks for the help Henk-

public class HomeController : Controller
{    
   private readonly IMemoryCache _cache;
   public IScheduledStuff _scheduledstuff;
   public HomeController(IMemoryCache cache, IScheduledStuff scheduledstuff)
   {
        _cache = cache;
        _scheduledstuff = scheduledstuff;
        _scheduledstuff.ScheduleItemsExecute();
    }
    public IActionResult Index()
    {
        ViewBag.ProductCategoryList = _cache.Get<IEnumerable<ProductCategory>>("Teststore");
        return View();
    }
}

public class ProductCategoryRepository : IProductCategoryRepository<ProductCategory>
{
    public IEnumerable<ProductCategory> GetAllProductCategory()
    {
        return _context.ProductCategory.ToList();
    }
}

public ProductCategory()
{
    public int ProductCategoryId { get; set; }
    public string ProductCategoryName { get; set; }
    public string ProductCategoryDescription { get; set; }
}

public class ScheduledStuff : IScheduledStuff
{
    private readonly DatabaseContext _context;
    IMemoryCache MemCache;
    public IProductCategoryRepository<ProductCategory> productcategoryrepository;

    public ScheduledStuff(DatabaseContext context, IMemoryCache memCache)
    {
        _context = context;
        MemCache = memCache;
        productcategoryrepository = new ProductCategoryRepository(_context);
    }

    public void ScheduleItemsExecute()
    {
        var testdata = productcategoryrepository.GetAllProductCategory();
        MemCache.Set("Teststore", testdata);
    }
}


public class Startup
{
    public IProductCategoryRepository<ProductCategory> productcategoryrepository;
    public IMemoryCache memorycache;

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddSingleton<ScheduledStuff>();
Sign up to request clarification or add additional context in comments.

Comments

-1

Cache is one of those few things that are good candidates for the Singleton design pattern. Plus, it is thread-safe. Just make a global cache object that is accessible to all that need it.

2 Comments

so to clarify, option one - global pattern, and don't place everthing in configureservices?
A static wrapper class that holds a reference to a static instance of MemoryCache. But, for testability, allow setting the instance of MemoryCache via a setter. Or, as @David says in his answer.
-1

I solved this issue with a static CacheHelper class. You can call this static class from any controller . You can get more ideas about how to implement it here: How to cache data in a MVC application

5 Comments

does not seem to work in net core 2, can you try it out?
I don't think the general pattern is subject to change with certain framework. Just make a "public static class CacheHelper" class and make a "GetFromCache" function that you can call from any controller. In your "GetFromCache" function you can request the object from cache, and if it isn't present you can call it from your database and fill the cache with it. You always return the object you need whether you got it from cache or from the database.
ok, well I was receiving a compilation error in netcore2 when trying out-
almost done writing static Memorycache, receiving error above though
You shouldn't initiate ProductCategoryStatic as a default value in the static class. When it get's there probably things aren't ready to call that, that's the reason of the error. Do it inside a procedure that you call to get the value. Something like this: GetValue { If (inCache) { get it from cache and return the value } else { get it from database, save it in cache and return the value } }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.