Где должно происходить кэширование в приложении ASP.NET MVC? - PullRequest
13 голосов
/ 25 октября 2008

Мне нужно кэшировать некоторые данные, используя System.Web.Caching.Cache . Не уверен, что это важно, но данные поступают не из базы данных, а из множества пользовательских объектов.

ASP.NET MVC является довольно новым для меня, и мне интересно, где имеет смысл это кэширование иметь место?

Модель или контроллер?

На некотором уровне имеет смысл кэшировать на уровне Model , но я не обязательно знаю последствия этого (если таковые имеются). Если кэширование должно выполняться на уровне Controller , это повлияет на все запросы или только на текущий HttpContext ?

Итак ... где должно выполняться кэширование данных приложения и каков хороший способ сделать это на самом деле?

Обновление

Спасибо за отличные ответы! Я все еще пытаюсь понять, где имеет смысл кэшировать данные при разных сценариях. Если кто-то кэширует всю страницу, то имеет смысл сохранять ее в представлении, но где провести черту, если она не вся страница?

Ответы [ 6 ]

7 голосов
/ 25 октября 2008

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

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

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

3 голосов
/ 05 декабря 2008

Быстрый ответ

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

Подробный ответ (потому что мне нравится звук моего голоса)

Вот пример.

[OutputCache(Duration=60, VaryByParam="None")]
public ActionResult CacheDemo() {
  return View();
}

Это означает, что если пользователь заходит на сайт (для требований к кешу, определенных в атрибуте), меньше работы нужно выполнить. Если есть только кэширование модели, то хотя логика (и, скорее всего, попадание в БД) кэшируется, веб-сервер все равно должен отображать страницу. Зачем это делать, когда результат рендеринга всегда будет одинаковым?

Итак, начните с OutputCach ing, затем переходите к кешированию моделей при тестировании производительности своего сайта.

Кэширование вывода также намного проще начать. Вам не нужно беспокоиться о распределенном кэшировании веб-фермы (если вы являетесь частью фермы) и поставщике кэширования для модели.

Продвинутые методы кэширования

Вы также можете применить кеширование пончиков -> кэшировать только часть страницы пользовательского интерфейса :) Проверьте это !

3 голосов
/ 25 октября 2008

Я не знаю ответа на ваш вопрос, но Джефф Этвуд рассказывает о том, как SO команда делала кеширование, используя инфраструктуру MVC для stackoverflow.com, на недавнем ханселтинговом шоу, которое может вам помочь:

http://www.hanselminutes.com/default.aspx?showID=152

2 голосов
/ 29 ноября 2008

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

Как насчет этого:

У меня есть несколько записей в модели, представленной классом Entry и источник записей (из базы данных, или «множество пользовательских объектов»). В модели я делаю интерфейс для извлечения записей:

public interface IEntryHandler
{
    IEnumerable<Entry> GetEntries();
}

В модели у меня есть фактическая реализация IEntryHandler где записи читаются из кеша и записываются в кеш.

public class EntryHandler : IEntryHandler
{
    public IEnumerable<Entry> GetEntries()
    {
        // Check if the objects are in the cache:
        List<Entry> entries = [Get entries from cache]
        if (entries == null)
        {
            // There were no entries in the cache, so we read them from the source:
            entries = [Get entries from database or 'plethora of custom objects']
            [Save the retrieved entries to cache for later use]
        }
        return entries;
    }
}

Затем контроллер будет вызывать IEntryHandler:

public class HomeController : Controller
{
    private IEntryHandler _entryHandler;

    // The default constructor, using cache and database/custom objects
    public HomeController()
        : this(new EntryHandler())
    {
    }

    // This constructor allows us to unit test the controller 
    // by writing a test class that implements IEntryHandler
    // but does not affect cache or entries in the database/custom objects
    public HomeController(IEntryHandler entryHandler)
    {
        _entryHandler = entryHandler;
    }

    // This controller action returns a list of entries to the view:
    public ActionResult Index()
    {
        return View(_entryHandler.GetEntries());
    }
}

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

1 голос
/ 27 октября 2008

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

Имейте в виду, что кеширование - очень сложная тема. Есть много разных мест, где вы можете хранить свой кеш:

  • Akamai / CDN кеширование
  • Кэширование в браузере
  • Кэширование приложений в памяти
  • Объект кэша .NET
  • Директива страницы
  • Распределенный кеш (memcached)
1 голос
/ 25 октября 2008

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

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

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