Я хочу сохранить маленький список простого объекта (содержащий три строки) в моем приложении MVC ASP.NET. Список загружается из базы данных, и это редко обновляется путем редактирования некоторых значений в администраторской области сайта.
Я думаю об использовании HttpContext. Текущий. Приложение для хранения его. Таким образом, я могу загрузить его в Global.asax:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
HttpContext.Current.Application["myObject"] = loadDataFromSql(); // returns my object
}
И затем может легко сослаться на него от любых контроллеров или представлений по мере необходимости. Затем в конечном счете администраторская область называет updateMyObject действие контроллера, я могу просто обновить DB и загрузить его в снова и замена HttpContext.Current.Application["myObject"]
.
Там какие-либо недостатки к выполнению этого? Кажется, что это будет хорошо работать, для какого я пытаюсь достигнуть, однако кто-либо знает о лучшем способе сделать это, предполагая, что существует некоторый главный недостаток к методу, который я разметил?
На самом деле вы делаете Кэширование , и это здорово, поскольку вы сокращаете количество обращений к внешнему хранилищу (базе данных или файлу, что угодно). Конечно, компромисс - это использование памяти. Теперь почти любая современная веб-платформа, включая ASP.NET, включает в себя какой-то механизм кэширования. Либо вы его используете, либо используете какую-то глобальную переменную.
Хранение данных во встроенном в ASP.NET объекте Cache
имеет ряд существенных преимуществ, поскольку этот механизм фактически проверяет использование памяти и удаляет кэшированные данные в соответствии с некоторыми правилами.
Однако, если данные, которые вы хотите кэшировать, интенсивно используются в приложении и их размер не слишком велик (скажем, менее 1 МБ), вы можете сохранить их как глобальную переменную.
В ASP.NET глобальные переменные достигаются либо с помощью объекта Application
, как вы описали в своем вопросе, либо путем записи общедоступных статических свойств / полей во внутреннем / общедоступном классе.
Вот мое решение статических свойств. Обратите внимание, что я использую объект блокировки, чтобы защитить внутренние данные от повреждения. Это выглядит так:
public class WhateverClass
{
private static object theLocker = new object();
private static YourDataType theData;
public static YourDataType TheData
{
get
{
lock (theLocker)
{
return theData;
}
}
set
{
lock (theLocker)
{
theData = value;
}
}
}
}
Использование очень просто:
Первый раз, в Application_Start:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
WhateverClass.TheData = loadDataFromSql();
}
В любом контроллере:
var myData = WhateverClass.TheData;
Этот подход лучше, потому что у вас есть безопасность типов, поскольку это общедоступное статическое свойство может быть явно объявлен с точным типом. Кроме того, этот тип хранилища более тестируемый, поскольку он не зависит от веб-контекста.
HTH!
HttpContext.Current.Application
по сути является пережитком, необходимым для обратной совместимости с классическим ASP. По сути, это статическая хеш-таблица с классической семантикой блокировки ASP (Application.Lock / Application.UnLock).
В качестве хеш-таблицы со слабой типизацией вам нужно будет преобразовывать объекты, которые вы извлекаете:
MyObject myObject = (MyObject) HttpContext.Current.Application["myObject"];
В приложении ASP.NET, которое не является миграцией классического ASP, я бы предпочел использовать другие стандартные элементы .NET, такие как:
Статическое поле, использующее семантику блокировки .NET, если вам нужна блокировка (например, ключевое слово блокировки C # или экземпляр ReaderWriterLockSlim, в зависимости от ваших требований):
static MyObject myObject = LoadFromSql ();
ASP .NET Cache - с богатой функциональностью для управления истечением срока действия, зависимостями и т. Д.
Если вы развертываете на одном веб-сервере, то подход сработает. Рассмотрите для этого объект Cache, поскольку он предоставляет больше возможностей для истечения срока действия, если вам нужна такая функциональность. (См. сравнение, хотя и устаревшее, здесь).
Если вы собираетесь развертывать на ферме веб-серверов или аналогичной ей, вам следует использовать memcached или другой удобный для веб-фермы механизм кэширования. Объекты Application и Cache обычно существуют только в контексте одного сервера; если ваш пользователь может заходить на несколько веб-серверов во время своей сессии (и кэш должен быть идентичным), вам понадобится общий кэш, который будет виден с каждого из потенциальных веб-серверов.
Независимо от того, какой путь вы выберете, вам нужно будет аннулировать/перезагружать кэш при каждом изменении базовых данных, что является пользовательским кодом, который зависит от приложения.
Этот подход хорошо работает и может значительно ускорить работу, но это немного больше работы, чем может показаться на первый взгляд...
Application_Start действительно запускается только при повторном использовании пула приложений, сбросе IIS или перезагрузке. Если вы обновляете эти значения нечасто, почему бы не сохранить их в своем web.config и не получить к ним доступ таким образом?
При этом я не думаю, что в вашем подходе есть что-то . Хотя чаще я видел людей, использующих файлы конфигурации для редко изменяемых значений.