ASP.NET无法缓存空值

时间:2009-06-09 02:26:07

标签: c# asp.net caching

有谁可以解释为什么你不能将空对象插入ASP.NET缓存?

string exampleItem = null;

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

异常错误消息指出“value”对象不能为null。在我的应用程序中,有正当理由说明我们为什么要在缓存中存储空值。

3 个答案:

答案 0 :(得分:20)

底层Cache可能是HashtableDictionary<string, object>,其getter不会区分该键的值,也不会区分该键的空值。

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

考虑使用占位符“null”项,类似于DbNull.Value

答案 1 :(得分:11)

澄清迈克尔·彼得罗塔接受的答案(评论太长了,我害怕),CacheInternal(CacheSingle和CacheMultiple,后者仅管理前者的多个实例)的具体实现,这是什么的公共Cache类型内部利用它来支持其Get,Add,Insert等方法,依靠HashTable进行存储。但是,HashTable中的特定键是否存在或不存在任何问题,因为本机(缓存)值不会直接存储在HashTable中。相反,HashTable填充了唯一的CacheEntry对象,这些对象包装缓存的键和值(CacheEntry实际上派生自CacheKey,添加基于对象的Value属性等等;非null值要求可以在其构造函数中找到)。

基于我对代码的阅读,作者没有明显的技术原因要求非空的CacheEntry.Value,除了公共Cache对象不公开Contains-或Exists-类型的方法,以及当然不公开内部底层的CacheEntry对象,它只返回CacheEntry值。因此,根据Michael的回答,在不强制值为非null的情况下,Cache对象用户无法知道特定键值是否存在。这也是可能的,但需要更多的代码读取才能确定,内部采用的相当复杂的方法来管理缓存的对象依赖关系,过期,事件和HashTable条目的就地更新可能在某种程度上依赖于值非空。

答案 2 :(得分:10)

作为一种可能的替代方案或解决方法,您可以改为存储对象而不是您的值。例如(假设您的值是一个字符串,但它可能是通用的)

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

...

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

这样你永远不会插入null。要获取值,只需从包装器中提取它:

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

(这一切都在我的头顶,所以对任何愚蠢的错别道歉。)