memcachedaspnetcore-environment

Aspnet Core persist In-Memory cache data on application startup


How to persist IMemorycache when I start and stop the website/debugging?. I was under the impression that IMemorycache is stored on the server and doesn't get impacted by website startup. Everytime I start and stop the website the IMemorycache entries are being reset to 0 cache.Set("entryA", "data1", cacheEntryOptions); First time this line is called in configure, I expect to have one entry in the cache after the line of code is executed. Next time within 5 seconds/minutes or before expiration time if I re-start the website (Startup is called. or stop and start debugging), there should be one entry in the cache even before the line of code gets executed. But that is not the way it is working. Is my understanding incorrect? I need a way to persist an item on the server for atleast 20min without losing everytime startup is called.

I see a similar post but not sure how the marked answer is a solution. What is the advantage of doing it in Program.cs vc configure. IMemoryCache does not save data at application startup

This is our code

using Microsoft.Extensions.Caching.Memory;
     public Startup(IHostingEnvironment env)
            {
                const string ENV_VARIABLE_SITENAME = "%WEBSITE_SITE_NAME%";
                var siteName = Environment.ExpandEnvironmentVariables(ENV_VARIABLE_SITENAME);
    
                if (string.IsNullOrEmpty(siteName) || siteName == ENV_VARIABLE_SITENAME)
                    siteName = System.Environment.MachineName;
    
                log.Info($"*******Site Name: '{siteName}' ************");
    
                var builder = new ConfigurationBuilder()
                    .SetBasePath(env.ContentRootPath)
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{siteName}.json", optional: false, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                    .AddEnvironmentVariables();
    
                Configuration = builder.Build();
                MyConfiguration = new class.Configuration(Configuration);
            }
    
    
           public void Configure(
                                IApplicationBuilder app,
                                IHostingEnvironment env,
                                ILoggerFactory loggerFactory,
                                IMemoryCache cache
                            )
                    {
                        if (env.IsDevelopment())
                        {
                            app.UseDeveloperExceptionPage();
                            // Use Swagger
                            //app = SwaggerServiceExtensions.UseSwaggerDocumentation(app);
                        }
                        else
                        {
                            //app.UseExceptionHandler("/Error");
                            app.UseHsts();
                        }
            
                        var cacheEntryOptions = new MemoryCacheEntryOptions()
                            .SetSize(1)//Size amount
                            //Priority on removing when reaching size limit (memory pressure)
                            .SetPriority(CacheItemPriority.High)
                            // Keep in cache for this time, reset time if accessed.
                            .SetSlidingExpiration(TimeSpan.FromMinutes(5))
                            // Remove from cache after this time, regardless of sliding expiration
                            .SetAbsoluteExpiration(TimeSpan.FromSeconds(10));
            
                        cache.Set("entryA", "data1", cacheEntryOptions);
                        
                        app.ConfigureExceptionHandler();
            
                        // Use Swagger
                        app = SwaggerServiceExtensions.UseSwaggerDocumentation(app);
            
            
                        }
            
            
            public void ConfigureServices(IServiceCollection services)
                    {
                        // for HttpContext
                        services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            
                        // need MVC
                        services.AddMvc(options =>
                        {
                            options.Filters.Add(new ErrorHandlingFilter());
                        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            
                        // Memory Cache
                        services.AddMemoryCache();
        }

Solution

  • Well, thats a pure Memory Cache and its an implementation thats not standing on its own, it's just code that runs within your code.

    And you seem to have a basic missunderstanding of how Dependency Injection works. Afaik the Memory Cache will only get materialized when it's first time being injected, not on invoking 'services.AddMemoryCache()'. As a matter of fact, the Cache is ready, when it's being and - by implementation - it will always come up as 100% new instance of the MemoryCache class - so there cannot be everything inside by the moment Startup() is being invoked and startup is being invoked when the application (re)starts. What youre actually looking for is a persisted caching solution, not a pure in-memory-cache.

    What you could do:

    1. Simplest solution: Use IDistributedCache with SQL for example. Thats a solution that stores the key/value pairs within DB, and thereby is persistent (but can be also in memory, if you use so-called memory optimized table), i run a 50 gb large db in such a fashion on SQL and can query results (via internet with the REST overhead and everything) within not even 1s.

    2. Implement the Mem Cache on its own small application, add a simple get/set REST API to acces it... that way the cache is independent from the app you currently develop - but, same issue... the default IMemoryCache isnt something thats meant to be persisted, the cache will always have to be manually renewed after application start.

    3. Switch to a persisted caching solution... e.g REDIS, MemCached etc, but thats a completely different task compared with the easy DistributedCache on DB option NET offers.