0

I'm trying to find the best way to store complex objects in a MemoryCache (specifically Microsoft.Extensions.Caching.Memory.MemoryCache).

My data's structure would be something as below:

public class Foo
{
    public Guid Id { get; set; }
    public IList<Bar> Bars { get; set; }
}

public class Bar
{
   public Guid Id { get; set; }
   public Guid ParentFooId { get; set; }
}

From an API call, I get some Foo instance with some Bars inside. It will be registered to a MemoryCache instance using:

CacheInstance = new MemoryCache();

CacheInstance.Set(fooInstance.Id, fooInstance);

//At some later point:
var cached = CacheInstance.Get<Foo>(foo.Id);

After this call, cached will be Foo, but cached.Bars will be empty.

Is there any way to store Foo an then retrieve it keeping the Bars inside?

[EDIT - SOLVED]

With the hints on the comments and the kind working example, I was able to track the issue.

There was another class Zee at some other point in the application.

As you might be imagining, it looks like:

public Class Zee
{
    public Guid Id { get; set; }
    public IList<Guid> FooIds { get; set }
}

When an instance of Zee was being cached, it was also running the FooIds and retrieving them from the API, but with an endpoint that would not include Bars.

As one might expect, the Foos present in cache where being overwritten by these incomplete versions.

Since all this procedure was going on with async calls, it was a little though to pinpoint "who" was overwriting.

Again, thank you very much for clearing my doubt about the MemoryCache mechanics and pointing me in the right direction!

4
  • 1
    Do you change your fooInstance after adding it to the Mem cache? Checking to see if you are aware that the cached object is by ref and if you change it afterwards it's gonna affect the cache. Judging by your sentence this seems to be a logical problem in your code Commented Aug 21, 2022 at 0:15
  • 1
    As mahdi pointed out, you are simply storing a reference to an object in memory cache. If you need a completely autonomous copy, you might want something like binary serialization via Message Pack. Commented Aug 21, 2022 at 2:51
  • 1
    I'd set a breakpoint on foo.bars.set and make sure your code does not set null to it.. For starters.. Commented Aug 21, 2022 at 5:25
  • Hi Carlos. It seems that you have found a solution to your problem. Instead of including the solution inside the question, it is much preferable to post is as a self-answer instead! Commented Aug 21, 2022 at 16:22

1 Answer 1

1

As I expected the Cache works (or I cant make it fail as you describe it), must be bug somewhere in your code. This is out of the box .NET 6 asp.net core app:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Caching.Memory;
using System.Diagnostics;

namespace WebApplication2.Pages
{
    public class Foo
    {
        public Guid Id { get; set; }
        public IList<Bar> Bars { get; set; }
    }

    public class Bar
    {
        public Guid Id { get; set; }
        public Guid ParentFooId { get; set; }
    }

    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;

        Guid fooid;
        Foo foo;
        MemoryCache CacheInstance;

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;

            fooid = Guid.NewGuid();
            foo = new Foo()
            {
                Id = fooid,
                Bars = new List<Bar>()
                {
                    new Bar() { Id = Guid.NewGuid(), ParentFooId = fooid },
                    new Bar() { Id = Guid.NewGuid(), ParentFooId = fooid },
                }
            };

            var opts = new MemoryCacheOptions() { CompactionPercentage = 0.50 };
            CacheInstance = new MemoryCache(opts);

            CacheInstance.Set(fooid, foo);

        }

        public ActionResult OnPostButtonClick(string data)
        {
            var cached = CacheInstance.Get<Foo>(fooid);
            var response = string.Format("Check Cache: foo: ({0}) bar: ({1})", cached == null ? "NULL" : "NOT NULL", cached?.Bars == null ? "NULL" : "NOT NULL");

            return new JsonResult("Cache Checked: " + response + " at " + DateTime.Now);
        }

        public void OnGet()
        {

        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.