Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MemoryCacheClient works differently than others - reference retained

I have a service that pulls statistics for a sales region. The service computes the stats for ALL regions and then caches that collection, then returns only the region requested.

public object Any(RegionTotals request)
{
    string cacheKey = "urn:RegionTotals";       

    //make sure master list is in the cache...
    base.Request.ToOptimizedResultUsingCache<RegionTotals>(
       base.Cache, cacheKey, CacheExpiryTime.DailyLoad(), () =>
       {
          return RegionTotalsFactory.GetObject();
       });

       //then retrieve them. This is all teams
       RegionTotals tots = base.Cache.Get<RegionTotals>(cacheKey);

       //remove all except requested 
       tots.Records.RemoveAll(o => o.RegionID != request.RegionID);

       return tots;
}

What I'm finding is that when I use a MemoryCacheClient (as part of a StaticAppHost that I use for Unit Tests), the line tots.Records.RemoveAll(...) actually affects the object in the cache. This means that I get the cached object, delete rows, and then the cache no longer contains all regions. Therefore, subsequent calls to this service for any other region return no records. If I use my normal Cache, of course the Cache.Get() makes a new copy of the object in the cache, and removing records from that object doesn't affect the cache.

like image 445
taglius Avatar asked Jul 12 '26 11:07

taglius


1 Answers

This is because an In Memory cache doesn't add any serialization overhead and just stores your object instances in memory. Whereas when you use any of the other Caching Providers your values are serialized first then sent to the remote Caching Provider then when it's retrieved it's deserialized back so it's never reusing the same object instances.

If you plan on mutating cached values you'll need to clone the instances before mutating them, if you don't want to manually implement ICloneable you can serialize and deserialize them with:

var clone = TypeSerializer.Clone(obj);
like image 188
mythz Avatar answered Jul 19 '26 01:07

mythz