ASP.NET can't cache null value

2019-02-11 18:13发布

Can anyone explain why you cannot insert a null object into the ASP.NET cache?

string exampleItem = null;

HttpRuntime.Cache.Insert("EXAMPLE_KEY", 
                        exampleItem, 
                        Nothing,                           
                        DateTime.Now.AddHours(1),
                        System.Web.Caching.Cache.NoSlidingExpiration);

The exception error message states that the "value" object cannot be null. In my application there are valid reasons why we whould want to store a null value in the cache.

3条回答
SAY GOODBYE
2楼-- · 2019-02-11 18:21

As a possible alternative or work-around, you can instead store an object rather than your value. For instance (this assumes your value is a string, but it could be generic)

public class CacheItemWrapper
{
    public string Value { get; set; }
}

...

cache.Insert(cacheKey, new CacheItemWrapper { Value = null }, ...);

That way you are never inserting null. To get the value back, you just extract it from the wrapper:

var val = cache.Get(cacheKey);
if (val != null) return val.Value;

(This is all off the top of my head, so apologies for any silly typos.)

查看更多
老娘就宠你
3楼-- · 2019-02-11 18:34

Underlying Cache is likely a Hashtable or Dictionary<string, object>, whose getters do not differentiate between no value at that key, or a null value at that key.

Hashtable table = new Hashtable();
object x = table["foo"];
table.Add("foo", null);
object y = table["foo"];
Console.WriteLine(x == y); // prints 'True'

Consider a using placeholder "null" item, similar to DbNull.Value.

查看更多
再贱就再见
4楼-- · 2019-02-11 18:36

To clarify Michael Petrotta's accepted answer a bit (too long for a comment, I'm afraid), the concrete implementations of CacheInternal (CacheSingle and CacheMultiple, the latter of which merely manages multiple instances of the former), which is what's utilized internally by the public Cache type to support its Get, Add, Insert, etc. methods, do rely on a HashTable for storage. However, there's never any question of whether there is or isn't a value for a particular key in the HashTable, because the native (cached) values aren't stored in the HashTable directly. Instead, the HashTable is filled with unique CacheEntry objects that wrap the cached keys and values (CacheEntry actually derives from CacheKey, adding an Object-based Value property, among other things; the non-null value requirement can be found in its constructor).

Based on my reading of the code, there's no obvious technical reason for the authors to have required a non-null CacheEntry.Value, except that the public Cache object doesn't expose a Contains- or Exists-type method, and of course doesn't expose the internal underlying CacheEntry objects, it only returns the CacheEntry values. So, as per Michael's answer, without forcing values to be non-null it isn't possible for Cache object users to know whether a particular key value exists. It's also possible, but would require more code reading to know for sure, that the rather complex approach taken internally to manage cached object dependencies, expirations, events, and in-place updates of HashTable entries might rely, in some way, on the values being non-null.

查看更多
登录 后发表回答