Я начинаю работать над инфраструктурой кэширования для моего сайта ASP.NET MVC. Проблема в том, что я не могу найти подходящее место для кэширования данных (кроме «везде»)
Сейчас моя архитектура выглядит так:
Контроллер -> Сервисный уровень -> Репозиторий. Хранилище использует Linq to SQL для доступа к данным.
Хранилище предоставляет универсальные методы, такие как Insert, GetById и GetQueryable, которые возвращают IQueryable, который сервисный уровень может дополнительно усовершенствовать.
Мне нравится идея поместить кэширование на уровень хранилища, так как на уровне службы не должно быть никакого значения, откуда берутся данные. Проблема, однако, заключается в недействительности кэша. Уровень обслуживания имеет больше информации о том, когда данные устаревают, чем хранилище. Например:
Предположим, у нас есть таблица Users и таблица Orders (канонический пример). Сервисный уровень предлагает такие методы, как GetOrder (int id), который вызовет уровень хранилища:
public Order GetOrder(int id)
{
using(var repo = _repoFactory.Create<Order>())
{
return repo.GetById(id)
}
}
или
repo.GetQueryable(order => order.Id == id && order.HasShipped == false).Single();
Если мы кешируем на уровне хранилища, кажется, что было бы очень ограниченно знать, когда изменились эти данные заказа. Предположим, что пользователь был удален, в результате чего все его заказы были удалены с помощью CASCADE. Служебный уровень может сделать недействительным кэш-память заказов, поскольку он знал, что пользователь был просто удален. Хранилище хотя (так как это единица работы), не будет знать. (Не обращайте внимания на тот факт, что мы не должны запрашивать заказы для удаленного пользователя, поскольку это всего лишь пример).
В других ситуациях я думаю, что это проявляется. Предположим, мы хотим получить все заказы пользователей:
repo.GetQueryable(order => order.UserId == userId).ToList()
Хранилище может кэшировать результаты этого запроса, но, если добавлен другой заказ, этот запрос больше не действителен. Только уровень сервиса знает об этом.
Также возможно, что мое понимание уровня хранилища неверно. Я как бы рассматриваю это как фасад вокруг источника данных (т. Е. Переходя с L2SQL на EF и т. Д., Сервисный уровень не знает о базовом источнике).