ASP.NET MVC - есть ли простой способ добавить кеширование данных в мой уровень обслуживания? - PullRequest
4 голосов
/ 25 июля 2010

У меня приложение MVC подключено так, что уровень репозитория запрашивает классы LINQ to SQL, уровень службы запрашивает уровень репозитория, а контроллеры вызывают уровень службы.

В основном у меня есть кодследующим образом

Репозиторий

    Public Function GetRegions() As IQueryable(Of Region) Implements IRegionRepository.GetRegions
        Dim region = (From r In dc.Regions
                 Select r)
        Return region.AsQueryable
    End Function

Сервис

    Public Function GetRegionById(ByVal id As Integer) As Region Implements IRegionService.GetRegionById
        Return _RegionRepository.GetRegions() _
            .Where(Function(r) (r.ID = id _
                                And r.isActive)) _
            .FirstOrDefault()
    End Function

    Public Function GetRegionByNameAndParentID(ByVal region As String, ByVal parentid As Integer) As Region Implements IRegionService.GetRegionByNameAndParentID
        Return _RegionRepository.GetRegions() _
            .Where(Function(r) (r.Region = region _
                                And r.ParentID = parentid _
                                And r.isActive)) _
            .FirstOrDefault()
    End Function

    Public Function GetActiveRegions() As List(Of Region) Implements IRegionService.GetActiveRegions
        Return _RegionRepository.GetRegions() _
            .Where(Function(r) r.isActive) _
            .ToList
    End Function

    Public Function GetAllRegions() As List(Of Region) Implements IRegionService.GetAllRegions
        Return _RegionRepository.GetRegions().ToList
    End Function

Мне интересно, есть ли хороший / эффективныйспособ добавить кеширование на сервисный уровень, чтобы не всегда вызывать REPO, если вызовы одинаковые.

Ответы [ 2 ]

1 голос
/ 25 июля 2010

Поскольку кеширование является сквозной задачей (выполните поиск в Википедии), вы можете использовать внедрение политики для реализации кэширования на уровне своего хранилища, но ограничением является то, что вы используете инфраструктуру DI, такую ​​как Castle, Unity, ... Преимущество концепция заключается в том, что вы сохраняете чистый код на уровне своего хранилища.

Я начну с «Это зависит», но в простом сценарии, где взаимодействие с другими сервисными агентами не требуется, рекомендуется только кэшировать доступ к базе данных, поскольку доступ к базе данных самый медленный из всех. Вот почему я бы рекомендовал не кэшировать доступ к уровню обслуживания, а скорее к уровню хранилища. Это также то, что Мартин Фаулер описывает в своей схеме отображения данных.

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

В вашем сценарии я бы прикрепил CachingHandler к вашему репозиторию GetRegions () и создал бы CacheKey, который объединяет, например, метод и параметры (если есть). В упрощенном подходе сохраните CacheKey и список результатов в Hashtable (в реальной жизни используйте блок приложения Patterns & Practices Caching или System.Web.Cache) и в каждом запросе к своему хранилищу проверьте, является ли ключ кэша в вашем Hashtable, затем верните кэшированный список.

Быстрый поиск в Google дает вам это, чтобы начать: http://entlib.codeplex.com/Thread/View.aspx?ThreadId=34190

1 голос
/ 25 июля 2010

rockinthesixstring - да, вы можете добавить кеш http в этот слой, используя анонимную функцию для извлечения из репозитория или извлечения из кеша.в основном, вы бы делали это по следующим строкам (это из приложения, над которым я сейчас работаю, которое использует дозвуковое, но предпосылка того, что вам нужно, идентична.

    /// <summary>
    /// Returns an IQueryable based on the passed-in Expression Database
    /// </summary>
    IQueryable<T> IRepository<T>.Find(Expression<Func<T, bool>> expression)
    {
        // set up our object cacheKey
        string keyValue = ParseExpression(expression);

        if(keyValue==null)
        {
            return _repository.Find(expression);
        }

        string cacheKey = string.Format(EntityrootList, _className, "Find", keyValue, DateTime.UtcNow.Ticks.ToString(), string.Empty);

        // try to populate from the cache
        // rockinthesixstring - this is the part that is most relevant to you
        var result = Cache.Get(cacheKey,
                                () => _repository.Find(expression),
                                CacheDuration);

        return result;
    }

[править] в контроллере, вы бы назвали это так (контроллер _repository установлен как:

readonly IRepository<Booking> _repository; 

в примере):

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ContentResult ListBookings(int shareholderid)
{
    Expression<Func<Booking, bool>> exprTree = x => x.FundShareholderEntity.ShareholderID == shareholderid;
    var bookings = _repository.Find(exprTree).OrderByDescending(x => x.BookingDetailEntity.ActualDateFrom).OrderBy(x => x.BookingTypeID);
    return Content(this.RenderPartialToString("BookingListNoPaging", bookings));
}

В приведенном выше примере Cache (т.е. Cache.Get ()) - это класс, который оборачивает кэш httpcontext более удобным для пользователя способом.

надеюсь, это поможет ...

jim

[править] - добавлен интерфейс кеша для добавления к «дебатам»:)

public interface ISessionCache
{
    T Get<T>(string key);
    T Get<T>(string key, Func<T> getUncachedItem, int cacheDuration);
    void Insert(string key, object obj, int cacheDuration, CacheDependency arg0, TimeSpan arg2);
    void Remove(string key);
    object this[string key] { get; } // default indexer
    IDictionaryEnumerator GetEnumerator();
}

в классе для инъекций будет использоваться следующим образом:

public class FakeCache : ISessionCache
{... all inteface members implemented here etc..}

или для httpcache:

public class HttpContextCache : ISessionCache
{... all inteface members implemented here etc..}

и т. Д. И т. Д. Еще раз ура - Джим

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