Использование HttpContext. Текущий. Приложение, чтобы хранить простые данные

Я хочу сохранить маленький список простого объекта (содержащий три строки) в моем приложении 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"].

Там какие-либо недостатки к выполнению этого? Кажется, что это будет хорошо работать, для какого я пытаюсь достигнуть, однако кто-либо знает о лучшем способе сделать это, предполагая, что существует некоторый главный недостаток к методу, который я разметил?

11
задан macca1 21 June 2010 в 03:33
поделиться

4 ответа

На самом деле вы делаете Кэширование , и это здорово, поскольку вы сокращаете количество обращений к внешнему хранилищу (базе данных или файлу, что угодно). Конечно, компромисс - это использование памяти. Теперь почти любая современная веб-платформа, включая 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!

32
ответ дан 3 December 2019 в 01:04
поделиться

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 - с богатой функциональностью для управления истечением срока действия, зависимостями и т. Д.

8
ответ дан 3 December 2019 в 01:04
поделиться

Если вы развертываете на одном веб-сервере, то подход сработает. Рассмотрите для этого объект Cache, поскольку он предоставляет больше возможностей для истечения срока действия, если вам нужна такая функциональность. (См. сравнение, хотя и устаревшее, здесь).

Если вы собираетесь развертывать на ферме веб-серверов или аналогичной ей, вам следует использовать memcached или другой удобный для веб-фермы механизм кэширования. Объекты Application и Cache обычно существуют только в контексте одного сервера; если ваш пользователь может заходить на несколько веб-серверов во время своей сессии (и кэш должен быть идентичным), вам понадобится общий кэш, который будет виден с каждого из потенциальных веб-серверов.

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

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

3
ответ дан 3 December 2019 в 01:04
поделиться

Application_Start действительно запускается только при повторном использовании пула приложений, сбросе IIS или перезагрузке. Если вы обновляете эти значения нечасто, почему бы не сохранить их в своем web.config и не получить к ним доступ таким образом?

При этом я не думаю, что в вашем подходе есть что-то . Хотя чаще я видел людей, использующих файлы конфигурации для редко изменяемых значений.

-1
ответ дан 3 December 2019 в 01:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: