ASP.NET не может кэшировать нулевое значение - PullRequest
19 голосов
/ 09 июня 2009

Может кто-нибудь объяснить, почему вы не можете вставить нулевой объект в кеш ASP.NET?

string exampleItem = null;

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

В сообщении об ошибке исключения говорится, что объект "значение" не может быть нулевым. В моем приложении есть веские причины, по которым мы хотели бы сохранить нулевое значение в кэше.

Ответы [ 3 ]

20 голосов
/ 09 июня 2009

В основе Cache, скорее всего, лежит Hashtable или Dictionary<string, object>, чьи геттеры не различают никакое значение для этого ключа или нулевое значение для этого ключа.

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

Рассмотрим использование пустого элемента-заполнителя, похожего на DbNull.Value.

11 голосов
/ 09 июня 2009

Чтобы немного разъяснить принятый ответ Майкла Петротты (боюсь, слишком долго для комментария), конкретные реализации CacheInternal (CacheSingle и CacheMultiple, последний из которых просто управляет несколькими экземплярами первого), что является используется внутренне общедоступным типом Cache для поддержки его методов Get, Add, Insert и т. д., для хранения используется HashTable. Однако никогда не возникает вопроса о том, существует или нет значение для конкретного ключа в HashTable, потому что собственные (кэшированные) значения не хранятся в HashTable напрямую. Вместо этого HashTable заполняется уникальными объектами CacheEntry, которые обертывают кэшированные ключи и значения (CacheEntry фактически наследуется от CacheKey, добавляя, среди прочего, свойство Object-Based Value; требование ненулевого значения можно найти в его конструкторе).

Исходя из моего прочтения кода, у авторов нет очевидных технических причин, по которым требуется CacheEntry.Value, отличный от NULL, за исключением того, что открытый объект Cache не предоставляет метод типа Contains- или Exists, и конечно, не раскрывает внутренние базовые объекты CacheEntry, он только возвращает значения CacheEntry. Таким образом, согласно ответу Михаэля, не заставляя значения быть ненулевыми, пользователи объекта Cache не смогут узнать, существует ли конкретное значение ключа. Это также возможно, но потребует больше чтения кода, чтобы точно знать, что довольно сложный подход, применяемый внутри компании для управления зависимостями кэшированных объектов, истечениями, событиями и обновлениями на месте записей HashTable, может в некоторой степени зависеть от значений будучи ненулевым.

10 голосов
/ 03 января 2013

В качестве возможной альтернативы или обходного пути вы можете вместо этого сохранить объект, а не свою ценность. Например (предполагается, что ваше значение является строкой, но оно может быть общим)

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

...

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

Таким образом, вы никогда не вставляете нуль. Чтобы вернуть значение, вы просто извлекаете его из оболочки:

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

(Это все из головы, поэтому извиняюсь за любые глупые опечатки.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...