1

I am taking small lookup table values from Entity Framework database and storing in MemoryCache. Currently using both ways, regular memoryCache, and Singleton MemoryContainer seen here Asp.Net Core: Use memory cache outside controller.

In Home Controller, this saves ProductTypes in a MemoryCache, and we see values store correctly in debug window (ProductType, ProductName, etc).

public class HomeController : Controller
{
    public IMemoryCache _memoryCache;
    public readonly StoreContext _storeContext;
    public MemoryContainer _memoryContainer;

    public HomeController(StoreContext storeContext, IMemoryCache memoryCache, MemoryContainer memoryContainer)
    {
        _storeContext= storeContext;
        _memoryCache = memoryCache;
        _memoryContainer = memoryContainer;
    }

    public IActionResult Index()
    {
        var productTypes = storeContext.ProductTypes;
        _memoryCache.Set("ProductTypesKey", productTypes );
        _memoryContainer._memoryCache.Set("ProductTypesKey2", test);
        return View();   //both values store correctly
    }

Then when going to ProductController,

public class ProductsController : Controller
{
    public StoreContext _storeContext;
    public IMemoryCache _memoryCache;
    public MemoryContainer _memoryContainer;

    public ProductsController(StoreContext storeContext, IMemoryCache memoryCache, MemoryContainer memoryContainer)
    {
        _storeContext = storeContext;
        _memoryCache = memoryCache;
        _memoryContainer = memoryContainer;
    }

    public async Task<IActionResult> Details(int? id)
    {
        var test =  _memoryCache.Get<DbSet<ProductTypes>>("ProductTypesKey");
        var test2 = _memoryContainer._memoryCache.Get<DbSet<ProductTypes>>("ProductTypesKey2");

I see the following error result in MemoryCache for both, how can this be fixed?

How do to make sure MemoryCache will get/store correctly with DbContext, regardless of going from Controller to Controller?

"Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.\r\nObject name: 'StoreContext'."

Other Code:

public class MemoryContainer
{
    public IMemoryCache _memoryCache { get; set; }
    public MemoryContainer(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }
}

Startup.cs

services.AddMemoryCache();
services.AddSingleton<MemoryContainer>();

Other Resources:

MVC Net Core Pass MemoryCache to All Controllers

  • The code you've shown looks fine. Q: Do you have a "using" block anywhere you're using this StoreContext and/or MemoryCache? – paulsm4 Oct 05 '19 at 20:09
  • I see - thank you for elaborating. Q: Is the [Singleton](https://stackoverflow.com/questions/42049576/) idea you cited above a good solution for you? – paulsm4 Oct 05 '19 at 21:13

1 Answers1

2

DbSet<T> implements IQueryable so those ProductTypes aren't really inside your application until materialized.

A simple ToList() will do the job:

var productTypes = storeContext.ProductTypes.ToList();

Then, inside the other controller:

var test =  _memoryCache.Get<List<ProductTypes>>("ProductTypesKey");

Calling ToList() on a DbSet without any filters isn't the best approach in all scenarios because it will load the whole sql table behind the DbSet. However, I guess this is kind of what you are trying to do, just make sure that you never do this on a table with a lot of data.

Note: you are seeing the data in debug window, because expanding IQueryable results actually performs sql queries.

edo.n
  • 2,184
  • 12
  • 12