System.Runtime.Caching.MemoryCache vs HttpRuntime.Cache - есть ли какие-то различия?

Мне интересно, существуют ли различия между MemoryCache и HttpRuntime.Cache, какой из них предпочтительнее в проектах ASP.NET MVC?

Насколько я понимаю, оба являются потокобезопасными, API с первого взгляда более или менее одинаковый, так что есть ли разница, когда использовать, который?

Ответ 1

HttpRuntime.Cache получает Cache для текущее приложение.

Класс MemoryCache похож на класс ASP.NET Cache.

Класс MemoryCache имеет много свойств и методов для доступа к кешу, который будет вам знаком, если вы использовали класс ASP.NET Cache.

Основное отличие между HttpRuntime.Cache и MemoryCache заключается в том, что последний был изменен, чтобы сделать его пригодным для использования приложениями .NET Framework, которые не являются приложениями ASP.NET.

Для дополнительного чтения:

Обновление:

По отзывам пользователей, иногда блог Jon davis не работает. Я положил всю статью как изображение. Пожалуйста, посмотрите на это.

Примечание: Если это не ясно, просто нажмите на изображение. После этого он откроется в браузере. Затем нажмите еще раз, чтобы увеличить:)

введите описание изображения здесь

Ответ 2

Вот статья Джона Дэвиса. Чтобы сохранить читаемость, я вырезаю теперь устаревший раздел EntLib, ввод, а также вывод.


Кэш ASP.NET

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

После очистки Google кажется, что довольно много людей, которые обсудили встроенные функции кеширования в .NET, прибегают к использованию кеша ASP.NET в своих не-веб-проектах. Это уже не самая доступная, самая поддерживаемая встроенная система кеширования в .NET; У .NET 4 есть ObjectCache, в который я попаду позже. Microsoft всегда была уверена, что кеш ASP.NET не предназначен для использования за пределами Интернета. Но многие люди все еще застряли в .NET 2.0 и .NET 3.5, и им нужно что-то работать, и это происходит для многих людей, хотя MSDN четко говорит:

Примечание. Класс Cache не предназначен для использования вне приложений ASP.NET. Он был разработан и протестирован для использования в ASP.NET для обеспечения кеширования для веб-приложений. В других типах приложений, таких как консольные приложения или приложения Windows Forms, кэширование ASP.NET может работать некорректно.

Класс для кеша ASP.NET - это System.Web.Caching.Cache в System.Web.dll. Однако вы не можете просто обновить объект Cache. Вы должны приобрести его из System.Web.HttpRuntime.Cache.

Cache cache = System.Web.HttpRuntime.Cache;

Работа с кешем ASP.NET документирована на MSDN здесь.

Плюсы:

  • Его встроенный.
  • Несмотря на синтаксис .NET 1.0, его довольно простой.
  • При использовании в веб-контексте его хорошо протестировано. Вне веб-контекстов, согласно поисковым запросам Google, обычно не вызывает проблем, несмотря на то, что Microsoft рекомендует отказаться от него, если вы используете .NET 2.0 или новее.
  • Вы можете быть уведомлены через делегата, когда элемент удален, что необходимо, если вам нужно сохранить его в живых, и вы не можете заранее установить приоритет элементов.
  • Отдельные элементы имеют гибкость любых (a), (b) или (c) методов истечения и удаления в списке методов удаления в верхней части этой статьи. Вы также можете связать действие с истечением срока действия с наличием физического файла.

Минусы:

  • Он не только статичен, но только один. Вы не можете создать свой собственный тип со своим статическим экземпляром кэша. У вас может быть только одно ведро для всего вашего приложения, период. Вы можете обернуть ведро своими собственными обертками, которые делают такие вещи, как pre-inject prefixes в ключах, и удаляют эти префиксы, когда вы вытаскиваете пары ключ/значение. Но есть еще только одно ведро. Все сосредоточено вместе. Это может быть реальной неприятностью, если, например, у вас есть служба, которая должна кэшировать три или четыре разных типа данных отдельно. Это не должно быть большой проблемой для простейших простых проектов. Но если проект имеет значительную степень сложности из-за его требований, кэш ASP.NET обычно не будет достаточным.
  • Элементы могут исчезать, волей-неволей. Многие люди знают об этом - я не был, пока не обновил свои знания об этой реализации кеша. По умолчанию кеш ASP.NET предназначен для уничтожения элементов, когда он "чувствует" себя. Более конкретно, см. (C) в моем определении таблицы кеша в верхней части этой статьи. Если другой поток в одном процессе работает над чем-то совершенно другим, и он сбрасывает высокоприоритетные элементы в кеш, то, как только .NET решает, что ему требуется некоторая память, он начнет уничтожать некоторые элементы в кеше в соответствии с их приоритеты, более низкие приоритеты. Все примеры, описанные здесь для добавления элементов кеша, используют приоритет по умолчанию, а не значение NotRemovable priority, которое не позволяет удалить его для целей очистки памяти, но все равно удалит его в соответствии с политикой истечения срока действия. Peppering CacheItemPriority.NotRemovable в кеш-вызовах может быть громоздким, в противном случае необходима оболочка.
  • Ключ должен быть строкой.Если, например, вы кэшируете записи данных, в которых записи заносятся в длинное или целое число, сначала необходимо преобразовать ключ в строку.
  • Синтаксис устарел. Его синтаксис .NET 1.0, даже более уродливый, чем ArrayList или Hashtable. Здесь нет дженериков, нет интерфейса IDictionary < > . У него нет метода Contains(), нет коллекции ключей, нет стандартных событий; он имеет только метод Get() плюс индекс, который делает то же самое, что и Get(), возвращая null, если нет совпадения, плюс Add(), Insert() (избыточно?), Remove() и GetEnumerator().
  • Игнорирует принцип DRY для настройки поведения по истечении срока действия по умолчанию, чтобы вы могли забыть о них. Вы должны явно указать кешу, как вы хотите, чтобы элемент, который вы добавляете, истекает или удаляется при каждом добавлении добавления элемента.
  • Невозможно получить доступ к элементам кэширования кэшированного элемента, например метку времени, когда она была добавлена. Инкапсуляция пошла немного за борт, затрудняя использование кеша, когда в коде вы пытаетесь определить, должен ли кэшированный элемент быть недействительным в отношении другого механизма кэширования (т.е. Сеансового набора) или нет.
  • События удаления не отображаются как события и должны отслеживаться во время добавления.
  • И если я этого не сказал, Microsoft явно рекомендует против него за пределами Интернета. И если youre проклят .NET 1.1, вы не должны использовать его с какой-либо уверенностью в стабильности вообще за пределами Интернета, так что не беспокойтесь.

.NET 4.0s ObjectCache/MemoryCache

Наконец, Microsoft реализовала абстрактный класс ObjectCache в последней версии .NET Framework и реализацию MemoryCache, которая наследует и реализует ObjectCache для целей в памяти в настройках, отличных от веб-сайтов.

System.Runtime.Caching.ObjectCache находится в сборке System.Runtime.Caching.dll. Это абстрактный класс, который объявляет в основном те же интерфейсы стиля .NET 1.0, которые находятся в кеше ASP.NET. System.Runtime.Caching.MemoryCache - это реализация ObjectCache в памяти и очень похожа на кеш ASP.NET с несколькими изменениями.

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

var config = new NameValueCollection();  
var cache = new MemoryCache("myMemCache", config);  
cache.Add(new CacheItem("a", "b"),  
    new CacheItemPolicy  
    {  
        Priority = CacheItemPriority.NotRemovable,  
        SlidingExpiration=TimeSpan.FromMinutes(30)  
    }); 

Плюсы:

  • Он встроен и теперь поддерживается и рекомендован Microsoft за пределами Интернета.
  • В отличие от кэша ASP.NET вы можете создать экземпляр объекта MemoryCache.

    Примечание: оно не должно быть статическим, но должно быть - Рекомендация Microsoft (см. желтый Предупреждение).

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

Минусы:

  • Все еще не полностью усиливает DRY. Из моего небольшого количества опыта вы все еще не можете установить однократное истечение срока действия TimeSpan и забыть об этом. И, откровенно говоря, хотя политика в примере выше, выше, более читаема, это требует ужасающей многословности.
  • Он по-прежнему не имеет общего ключа; для этого требуется строка в качестве ключа. Таким образом, вы не можете хранить как long или int, если вы кэшируете записи данных, если только вы не конвертируете в строку.

Сделай сам: создай сам

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

  • Создайте класс контейнера значений, называемый как Expending или Expired, который будет содержать значение типа T, свойство TimeStamp типа DateTime для хранения, когда значение было добавлено в кэш, и TimeSpan, который указывает, насколько далеко от отметка времени, в которой элемент должен истечь. Для явного истечения срока действия вы можете просто выставить свойство setter, которое устанавливает TimeSpan, учитывая дату, вычитаемую временной меткой.
  • Создайте класс, назовем его ExpirableItemsDictionary, который реализует IDictionary. Я предпочитаю сделать его общим классом, определенным потребителем.
  • В классе, созданном в # 2, добавьте словарь > как свойство и назовите его InnerDictionary.
  • Реализация, если IDictionary в классе, созданном в # 2, должен использовать InnerDictionary для хранения кешированных элементов. Инкапсуляция скроет детали метода кеширования через экземпляры типа, созданного в # 1 выше.
  • Убедитесь, что указатель (this []), ContainsKey() и т.д. осторожно очищает истекшие элементы и удаляет устаревшие элементы перед возвратом значения. Возвращает null в getters, если элемент был удален.
  • Используйте блокировки потоков на всех геттерах, сеттерах, ContainsKey() и, особенно, при очистке истекших элементов.
  • Поднять событие всякий раз, когда элемент удаляется из-за истечения срока действия.
  • Добавьте экземпляр System.Threading.Timer и установите его во время инициализации, чтобы автоматически удалять истекшие элементы каждые 15 секунд. Это то же поведение, что и кеш ASP.NET.
  • Возможно, вы захотите добавить процедуру AddOrUpdate(), которая выталкивает скользящее окончание, заменяя метку времени на контейнере элементов (истекающий экземпляр), если она уже существует.

Microsoft должна поддерживать свои оригинальные проекты, потому что их пользовательская база создала зависимость от них, но это не значит, что они хорошие проекты.

Плюсы:

  • У вас есть полный контроль.
  • Может усилить DRY, настроив поведение кэширования по умолчанию, а затем просто отбрасывая пары ключ/значение без объявления данных кэширования каждый раз, когда вы добавляете элемент.
  • Может реализовывать современные интерфейсы, а именно IDictionary<K,T>. Это значительно облегчает использование, поскольку его интерфейс более предсказуем как интерфейс словаря, а также делает его более доступным для помощников и методов расширения, которые работают с IDictionary < > .
  • Сведения о кэшировании могут быть неинкапсулированы, например, выставляя свой InnerDictionary через общедоступное свойство только для чтения, позволяя писать явные модульные тесты против вашей стратегии кэширования, а также расширять базовую реализацию кэширования с помощью дополнительные стратегии кэширования, которые основываются на нем.
  • Несмотря на то, что это не обязательно знакомый интерфейс для тех, кто уже привык к синтаксису стиля .NET 1.0 кэша ASP.NET или к блоку приложения кэширования, вы можете определить интерфейс, чтобы выглядите, как будто вы хотите, чтобы он выглядел.
  • Может использовать любой тип для ключей. Это одна из причин создания дженериков. Не все должно быть связано с строкой.

Минусы:

  • Не придумана и не одобрена Microsoft, поэтому она не будет иметь одинаковую гарантию качества.
  • Предполагая, что реализованы только описанные выше инструкции, не очищает ли "волей-неволей" элементы для освобождения памяти в приоритетном порядке (это, в любом случае, функция утилиты для использования в любом случае в кэше). BUY RAM, где бы вы ни были используя кеш, оперативная память дешевая).

Среди всех четырех из этих вариантов это мое предпочтение. Я реализовал это основное кэширующее решение. Пока что это работает отлично, нет известных ошибок (пожалуйста, свяжитесь со мной с комментариями ниже или в jon-at-jondavis, если они есть!!), и я намерен использовать его во всех моих небольших проектах, которые вам нужны базовое кэширование. Вот он:

Ссылка Github: https://github.com/kroimon/ExpirableItemDictionary

Старая ссылка: ExpirableItemDictionary.zip

Достойна упоминания: AppFabric, NoSQL, Et Al

Обратите внимание, что в заголовке этой статьи в блоге указано "Простое кэширование", а не "Кэш-память с большой нагрузкой". Если вы хотите попасть в тяжелые вещи, вы должны посмотреть на выделенные, масштабные решения.

Ответ 3

MemoryCache - это то, что он говорит, кеш, хранящийся в памяти

HttpRuntime.Cache(см. http://msdn.microsoft.com/en-us/library/system.web.httpruntime.cache(v=vs.100).aspx и http://msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx) сохраняется до того, что вы настроите в своем приложении.

см., например, "ASP.NET 4.0: создание пользовательских поставщиков кэшей вывода" http://weblogs.asp.net/gunnarpeipman/archive/2009/11/19/asp-net-4-0-writing-custom-output-cache-providers.aspx