Правильная реализация кеша в библиотеке классов для использования в приложении asp.net

Я реализую кеш в библиотеке классов, которую использую в приложении asp.net.

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

MyCacheObject.Instance.MyDataCollection

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

MyOtherCacheObject.Instance.MyOtherDataCollection(indexkey)

На этот раз был поднят вопрос о вывозе мусора. Поскольку я храню огромное количество данных, не будет ли напрасной тратой времени, если они внезапно будут удалены? Поскольку это всего лишь одноэлементный шаблон, ничто не гарантирует, что данные останутся в кеше.

Итак, мой вопрос: как лучше всего реализовать кеш для обработки этой ситуации? Мне действительно не нравится огромное сложное решение для этого, и я знаю, что в System.Web есть кеширование, но это кажется немного «неправильным», поскольку это просто библиотека классов, или что вы думаете?


person Per Hornshøj-Schierbeck    schedule 01.10.2008    source источник


Ответы (2)


На мой взгляд, лучшим решением будут следующие характеристики:

  • Использует доступные службы кэширования, предоставляемые платформой, стараясь не писать свои собственные.

  • Не связывает вашу библиотеку классов с System.Web, чтобы слои были согласованными.

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

Итак, я бы использовал стратегию IoC, чтобы позволить библиотеке классов использовать различные реализации кэширования в зависимости от среды, в которой она работает.

Предположим, вы определяете свой абстрактный контракт кэширования как:

public interface ICacheService 
{
    AddItem(...);
}

Вы можете предоставить реализацию на основе System.Web:

public AspNetBasedCacheService : ICacheService
{
    AddItem(...)
    {
        // Implementation that uses the HttpContext.Cache object
    }
 }

А затем опубликуйте эту реализацию как синглтон. Обратите внимание, что разница с вашим первоначальным подходом заключается в том, что синглтон - это просто ссылка на реализацию на основе службы кеша ASP.NET, а не на полный "объект кеша".

public class CacheServiceProvider 
{
    public static ICacheService Instance {get; set;}

}

Вам придется инициализировать реализацию кэширования либо путем выполнения ленивой инициализации, либо при запуске приложения (в Global.asax.cs)

И каждый компонент домена сможет использовать опубликованную службу кэширования, не зная, что она реализована на базе System.Web.

// inside your class library:
ICacheService cache = CacheServiceProvider.Instance;
cache.AddItem(...);

Я согласен, что это, вероятно, не самое простое решение, но я стремлюсь использовать преимущества реализации кэша ASP.NET, не жертвуя развязкой кода и гибкостью.

Надеюсь, я правильно понял ваш вопрос.

person Sergio Acosta    schedule 01.10.2008
comment
Мне нравится то, к чему вы клоните (хотя я бы избегал IoC). Вы поднимаете некоторые хорошие идеи, которые я могу запустить с тем не менее. Спасибо - person Per Hornshøj-Schierbeck; 01.10.2008
comment
Вы также можете добавить резервную переменную и выполнить блокировку этой переменной, если набор выполнен. Моя интуиция подсказывает, что это может предотвратить некоторые проблемы с потоками. - person Kees C. Bakker; 26.03.2011

Данные не будут собирать мусор, пока кеш все еще содержит ссылку на них.

Кроме того, никогда не используйте синглтоны.

person 1800 INFORMATION    schedule 01.10.2008
comment
но я боюсь, что cacheobject получит gc'ed, а не данные, которые он кэширует. - person Per Hornshøj-Schierbeck; 01.10.2008
comment
также вместо того, чтобы использовать синглтон для хранения моего кеша, что было бы лучше? - person Per Hornshøj-Schierbeck; 01.10.2008
comment
Почему объект кеша собирает мусор? Пока есть ссылка на него, этого не может быть - person 1800 INFORMATION; 01.10.2008
comment
Кроме того, никогда не используйте синглтоны. - для синглтонов все еще есть законное использование, особенно для реализации интерфейса (поскольку у вас не может быть статических интерфейсов). - person Marc Gravell; 01.10.2008
comment
Я к тому, что где эта ссылка? Ссылка будет существовать только во время запроса страницы asp.net. Предполагая, что сайт находится под большой нагрузкой, может быть по крайней мере одна ссылка за раз, но это не сайт с очень большим количеством пользователей, так кто там, чтобы держать ссылку? - person Per Hornshøj-Schierbeck; 01.10.2008
comment
Похоже, ваш Singleton (который, кстати, никогда не следует использовать) на самом деле является глобальной переменной для каждой страницы в этом случае. - person 1800 INFORMATION; 01.10.2008
comment
Если я никогда не должен использовать его, что я должен использовать вместо этого? - person Per Hornshøj-Schierbeck; 01.10.2008
comment
Что ж, если вы действительно думаете, что вам нужно только одно из чего-то, тогда хороший метод — создать только одно из этих вещей, а затем передать его любым объектам, которым это нужно. - person 1800 INFORMATION; 01.10.2008
comment
Но нескольким объектам нужна эта одна вещь, и я не знаю, какой из них понадобится/создаст ее в первую очередь. - person Per Hornshøj-Schierbeck; 01.10.2008