views:

759

answers:

7

Hi,

I want to permanently add an item to the cache. I am using the following syntax:

HttpContext.Current.Cache.Insert(cacheName, c, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);

I have found out, that ASP.NET still sometimes removes items from the cache.

Any ideas on how to prevent this (in addition to dropping the cache and using Dictionary stored in a static member?

Matra

A: 

If you want something stored in memory permanently (i.e. for the life of the AppDomain) then a static field (in your case, a Dictionary<TKey,TValue>) is your best bet.

Once the CLR has loaded the containing type into memory your Dictionary will be held in memory until the AppDomain unloads.

Andrew Hare
+3  A: 

You can't prevent ASP.NET from removing items from the cache (e.g. when memory gets low).

If you need to store data for the whole lifetime of the application, then put it into the ApplicationState collection, e.g:

Application["myData"] = ...;

This is similar to the SessionState collection, but as the name says, it's application-wide.

M4N
A: 

You cannot ever completely prevent something from being removed from the ASP.NET Cache (i.e. the HttpContext.Current.Cache object) and this is very much by design.

Please see the section in the MSDN Article ASP.NET Caching Overview called "Automatic Data Removal", which gives the most pertinent information regarding items being removed from the cache.

It states:

ASP.NET can remove data from the cache for one of these reasons:

  • Because memory on the server is low, a process known as scavenging.
  • Because the item in the cache has expired.
  • Because the item's dependency changes.

To help you manage cached items, ASP.NET can notify your application when items are removed from the cache.

Scavenging is the process of deleting items from the cache when memory is scarce. Items are removed when they have not been accessed in some time or when items are marked as low priority when added to the cache. ASP.NET uses the CacheItemPriority object to determine which items to scavenge first. For more information see How to: Add Items to the Cache.

It's for this reason (Scavenging, if no other) that you can never absolutely rely upon an item that you may have previously placed in the Cache and explicitly marked it with NoSlidingExpiration and NoAbsoluteExpiration, and possibly even marked it as a high priority item, as still being there in the Cache at a later point in time.

CraigTP
A: 

You should be prepared to handle a cache miss and reload the information in your cache as required. See here

ozczecho
A: 

Use Cache.Add() and set the cache priority extremely high(CacheItemPriority.NotRemovable), this will help it stay in the cache.

HttpContext.Current.Cache.Add("key", "your object", null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null);

System.Web.Caching.CacheItemPriority.NotRemovable

This still seems to not guarantee it being in the cache, but it also sets it so high its highly unlikely that it will be... but you will still need to check if its there and re-cache if not... (looks like some people on the intertubes don't like using this high a cache setting... and some do... depends on your exact scenario i guess...)

public static string GetSpecialObject
{
    get
    {
        object obj = HttpContext.Current.Cache["key"];
        if (obj  == null)
        {
            obj = HttpContext.Current.Cache.Add("key", 
                                            "I stay in cache as best i can object", // Build Object Function Here
                                            null, 
                                            Cache.NoAbsoluteExpiration, 
                                            Cache.NoSlidingExpiration, 
                                            CacheItemPriority.NotRemovable, 
                                            null);
        }
        return (string)obj;
    }
}

good luck

BigBlondeViking
+1  A: 

You can't prevent ASP.NET from removing items from the cache (e.g. when memory gets low).

You cannot ever completely prevent something from being removed from the ASP.NET Cache (i.e. the HttpContext.Current.Cache object) and this is very much by design.

Wrong! You CAN prevent your items from being removed from the asp.net cache if you mark the item with CacheItemPriority.NotRemovable. Each and every other cached data (application, session, etc...) are stored in the HttpRuntime cache this way.

People always tend to believe that even this priority doesn't prevent your data to expire, but this is due to the lack of proper documentation. I think the confussion comes with the ability to manually remove such an item from the cache OR the item being removed due to dependencies setted for it.

So, if you never manually remove it, and never specify dependencies that can get it removed, you have your item in there for the life of the appdomain.

Runtime, Have you tested it? Answer from BigBlondeVikingindicates that this kind of items might still get removed.
Matra, yes I've tested it. The confusion comes with the ability to manually remove an item with such a priority, and also automatically have it removed either by specifying some time-based expiration or some dependency. So, NotRemovable does NOT mean once you cache it it HAS TO stay there for the life of the appdomain. NotRemovable means that ms implementation will not remove such an item when you get low on memory. This is how inproc session state is held in cache. If all of your items are NotRemovable and you cache past your mem capacity, you'll get OutOfMemory.
A: 

And what happens if all the items stored in the Cache are NotRemovable? When memory gets scares, what happens?

Sil