views:

719

answers:

4

Hi folks,

From MSDN about the differences between Adding or Inserting an item the ASP.NET Cache:

Note: The Add and Insert methods have the same signature, but there are subtle differences between them. First, calling the Add method returns an object that represents the cached item, while calling Insert does not. Second, their behavior is different if you call these methods and add an item to the Cache that is already stored there. The Insert method replaces the item, while the Add method fails. [emphasis mine]

The second part is easy. No question about that.

But with the first part, why would it want to return an object that represents the cached item? If I'm trying to Add an item to the cache, I already have/know what that item is?

I don't get it. What is the reasoning behind this?

A: 

It only returns an object if the same object was already stored in the cache (under another key I guess under the same key). Otherwise it returns null. The documentation is misleading:

http://msdn.microsoft.com/en-us/library/system.web.caching.cache.add.aspx

Looking at it in Reflector, both methods seem to call the same internal method, with ADD returning the old object previously stored under the same key, and the INSERT method simply ignoring that value.

kitsune
Dude, that doesn't sound right :( It adds an item if it's not there, otherwise it *fails* (expection thrown?? can't remember). It also returns the an object. How can it return the same object, under another key?? that makes no sense..
Pure.Krome
It doesn't, but it says so in the documentation"Return value: An Object if the item was previously stored in the Cache; otherwise, null reference (Nothing in Visual Basic)."If it fails if there is already an object cached under that key, how can it say that it returns an object if that object is already cached? Under what key?Again, I don't think that's happening, so the documentation doesn't really make sense...
kitsune
+2  A: 

If the Add method call succeeds in adding the item, it returns null.

If the key already exists in the cache, the method returns an object. However, the documentation doesn't say if it returns the object that you tried to put in the cache or the object already stored in the cache.

Logically it should return the object already in the cache, as that is the only information that is interresting. You already have a reference to the object that you try to put in the cache.

Guffa
Thanks mate - now that makes sense :)
Pure.Krome
+8  A: 

Calling Add() on a cache eventually calls an internal method with this signature:

internal abstract CacheEntry UpdateCache(CacheKey cacheKey, 
    CacheEntry newEntry, bool replace, CacheItemRemovedReason removedReason, 
    out object valueOld);

Notice the out object valueOld - this gets set to the object that is currently in the "cacheKey" location in the cache, and is returned as the result of Add(). The documentation is misleading, it's not actually the same object that is returned - it's whatever object was at that same key location.

This is easily verified with the following code:

 String x = "lorem";
 String y = "ipsum";

 HttpContext.Current.Cache.Add("hi", x, null, DateTime.MaxValue, 
                               Cache.NoSlidingExpiration, 
                               CacheItemPriority.Normal, null);

 var z = HttpContext.Current.Cache.Add("hi", y, null, DateTime.MaxValue,
                              Cache.NoSlidingExpiration, 
                              CacheItemPriority.Normal, null);

 //Result:
 //   z == "lorem"
womp
That's what makes sense and what I presumed initially... it's possible to override a key's value and the old value is returned.
kitsune
To the original poster, this is an easy way to check whether a cached object was updated or not...
kitsune
+4  A: 

To make this even clearer, here's a console app that demonstrates the exact behavior:

static void Main(string[] args)
{
    string key = "key";

    HttpRuntime.Cache.Add(key, "first", null/*no depends*/, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null/*no callback*/);
    var addResult = HttpRuntime.Cache.Add(key, "second", null/*no depends*/, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null/*no callback*/);

    Console.WriteLine("addResult = {0}", addResult);
    Console.WriteLine("Cache[key] = {0}", HttpRuntime.Cache[key]);
}

And the console output:

addResult = first
Cache[key] = first

The "second" call to .Add returns what is currently in the Cache under our key and fails to update the entry!

Jarrod Dixon