[asp.net-mvc] MVC 응용 프로그램에서 데이터를 캐시하는 방법

MVC 응용 프로그램의 페이지 캐싱 및 부분 페이지 캐싱에 대한 많은 정보를 읽었습니다. 그러나 데이터를 캐시하는 방법을 알고 싶습니다.

내 시나리오에서는 LINQ to Entities (엔터티 프레임 워크)를 사용합니다. GetNames (또는 메소드가 무엇이든)에 대한 첫 번째 호출에서 데이터베이스의 데이터를 가져오고 싶습니다. 캐시 된 버전을 사용하기 위해 결과를 캐시에 저장하고 두 번째 호출에서 결과를 저장하고 싶습니다.

누구나 이것이 어떻게 작동하는지, 어디에서 구현 해야하는지 (모델?) 및 작동하는지에 대한 예를 보여줄 수 있습니까?

나는 전형적인 ASP.NET 앱에서 일반적으로 매우 정적 인 데이터를 위해 이것을 보았습니다.



답변

모델에서 System.Web dll을 참조하고 System.Web.Caching.Cache를 사용하십시오.

    public string[] GetNames()
    {
      string[] names = Cache["names"] as string[];
      if(names == null) //not in cache
      {
        names = DB.GetNames();
        Cache["names"] = names;
      }
      return names;
    }

조금 단순화되었지만 그것이 효과가 있다고 생각합니다. 이것은 MVC와 관련이 없으며 항상 데이터 캐싱에이 방법을 사용했습니다.


답변

내가 사용하는 멋지고 간단한 캐시 도우미 클래스 / 서비스는 다음과 같습니다.

using System.Runtime.Caching;  

public class InMemoryCache: ICacheService
{
    public T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class
    {
        T item = MemoryCache.Default.Get(cacheKey) as T;
        if (item == null)
        {
            item = getItemCallback();
            MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(10));
        }
        return item;
    }
}

interface ICacheService
{
    T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class;
}

용법:

cacheProvider.GetOrSet("cache key", (delegate method if cache is empty));

캐시 공급자는 캐시에 “캐시 id”라는 이름의 것이 있는지 확인하고,없는 경우 데이터를 가져 와서 캐시에 저장하기 위해 대리자 메서드를 호출합니다.

예:

var products=cacheService.GetOrSet("catalog.products", ()=>productRepository.GetAll())


답변

TT의 게시물을 언급하고 있으며 다음과 같은 접근법을 제안합니다.

모델에서 System.Web dll을 참조하고 System.Web.Caching.Cache를 사용하십시오.

public string[] GetNames()
{ 
    var noms = Cache["names"];
    if(noms == null) 
    {    
        noms = DB.GetNames();
        Cache["names"] = noms; 
    }

    return ((string[])noms);
}

캐시에서 다시 읽은 값을 반환하면 안됩니다. 특정 시점에서 값이 여전히 캐시에 있는지 알 수 없기 때문입니다. 이전에 명령문에 삽입 한 경우에도 이미 사라 졌거나 캐시에 추가되지 않은 것일 수 있습니다.

따라서 데이터베이스에서 읽은 데이터를 추가하고 캐시에서 다시 읽지 않고 직접 반환합니다.


답변

.NET 4.5+ 프레임 워크

참조 추가 : System.Runtime.Caching

using 문 추가 :
using System.Runtime.Caching;

public string[] GetNames()
{ 
    var noms = System.Runtime.Caching.MemoryCache.Default["names"];
    if(noms == null) 
    {    
        noms = DB.GetNames();
        System.Runtime.Caching.MemoryCache.Default["names"] = noms; 
    }

    return ((string[])noms);
}

.NET Framework 3.5 및 이전 버전에서 ASP.NET은 System.Web.Caching 네임 스페이스에서 메모리 내 캐시 구현을 제공했습니다. 이전 버전의 .NET Framework에서는 캐싱이 System.Web 네임 스페이스에서만 사용 가능하므로 ASP.NET 클래스에 대한 종속성이 필요했습니다. .NET Framework 4에서 System.Runtime.Caching 네임 스페이스에는 웹 및 웹 이외의 응용 프로그램 모두를 위해 설계된 API가 포함되어 있습니다.

더 많은 정보:


답변

Steve Smith는 ASP.NET MVC에서 CachedRepository 패턴을 사용하는 방법을 보여주는 두 개의 훌륭한 블로그 게시물을 작성했습니다. 리포지토리 패턴을 효과적으로 사용하므로 기존 코드를 변경하지 않고도 캐싱을 수행 할 수 있습니다.

http://ardalis.com/Introducing-the-CachedRepository-Pattern

http://ardalis.com/building-a-cachedrepository-via-strategy-pattern

이 두 게시물에서 그는이 패턴을 설정하는 방법을 보여주고 왜 유용한 지 설명합니다. 이 패턴을 사용하면 기존 코드 없이도 캐싱 로직을 보지 않고도 캐싱 할 수 있습니다. 기본적으로 캐시 된 저장소는 다른 저장소 인 것처럼 사용합니다.


답변

AppFabric Caching 은 여러 서버의 물리적 메모리를 사용하여 키-값 쌍으로 데이터를 저장하는 인 메모리 캐싱 기술입니다. AppFabric은 .NET Framework 응용 프로그램의 성능 및 확장 성 향상을 제공합니다. 개념과 아키텍처


답변

@Hrvoje Hudo의 답변 연장 …

암호:

using System;
using System.Runtime.Caching;

public class InMemoryCache : ICacheService
{
    public TValue Get<TValue>(string cacheKey, int durationInMinutes, Func<TValue> getItemCallback) where TValue : class
    {
        TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
        if (item == null)
        {
            item = getItemCallback();
            MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
        }
        return item;
    }

    public TValue Get<TValue, TId>(string cacheKeyFormat, TId id, int durationInMinutes, Func<TId, TValue> getItemCallback) where TValue : class
    {
        string cacheKey = string.Format(cacheKeyFormat, id);
        TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
        if (item == null)
        {
            item = getItemCallback(id);
            MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
        }
        return item;
    }
}

interface ICacheService
{
    TValue Get<TValue>(string cacheKey, Func<TValue> getItemCallback) where TValue : class;
    TValue Get<TValue, TId>(string cacheKeyFormat, TId id, Func<TId, TValue> getItemCallback) where TValue : class;
}

단일 항목 캐싱 (항목 유형에 대한 전체 카탈로그를 캐싱하기 때문에 각 항목이 ID를 기반으로 캐시되는 경우)

Product product = cache.Get("product_{0}", productId, 10, productData.getProductById);

모든 것을 캐싱

IEnumerable<Categories> categories = cache.Get("categories", 20, categoryData.getCategories);

왜 TI

두 번째 도우미는 대부분의 데이터 키가 복합적이지 않기 때문에 특히 좋습니다. 복합 키를 자주 사용하는 경우 추가 방법을 추가 할 수 있습니다. 이런 식으로 모든 종류의 문자열 연결 또는 문자열을 피할 수 있습니다. 키를 캐시 도우미에 전달하기위한 형식. 또한 래퍼 메소드에 ID를 전달할 필요가 없기 때문에 데이터 액세스 메소드를 더 쉽게 전달할 수 있습니다. 모든 것이 매우 간결하고 대부분의 사용 사례에 맞게 구성됩니다.