2013-05-08 21 views
29

Mam potrzebę buforowania kolekcji obiektów, które są w większości statyczne (mogą mieć zmiany 1x dziennie), które są dostępne w mojej usłudze API ASP ASP.NET Web OData. Ten zestaw wyników jest używany w odniesieniu do wywołań (co oznacza, że ​​nie jest zależny od klienta), więc musi być buforowany na poziomie aplikacji.Buforowanie danych w Web API

Zrobiłem kilka wyszukiwania na "buforowanie w Web API", ale wszystkie wyniki dotyczyły "buforowania danych wyjściowych". Nie tego tutaj szukam. Chcę przechowywać w pamięci podręcznej kolekcję "Ludzie" do ponownego użycia w kolejnych połączeniach (może mieć wygaszenie poślizgu).

Moje pytanie brzmi, ponieważ jest to po prostu ASP.NET, czy używam tradycyjnych technik buforowania aplikacji do utrzymywania tej kolekcji w pamięci, czy jest coś innego, co muszę zrobić? Kolekcja ta jest , a nie bezpośrednio zwracana do użytkownika, ale raczej używana jako źródło za kulisami zapytań OData za pośrednictwem wywołań API. Nie ma powodu, abym przychodził do bazy danych podczas każdego połączenia, aby uzyskać dokładne informacje o każdym połączeniu. Wygasanie co godzinę powinno wystarczyć.

Ktoś wie, jak poprawnie buforować dane w tym scenariuszu?

Odpowiedz

21

Tak, buforowanie wyjścia nie jest tym, czego szukasz. Możesz buforować dane w pamięci za pomocą MemoryCache, na przykład http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx. Jednak utracisz te dane, jeśli pula aplikacji zostanie poddana recyklingowi. Inną opcją jest użycie rozproszonej pamięci podręcznej, takiej jak AppFabric Cache lub MemCache, aby wymienić tylko kilka.

+0

Tak po napisaniu tego znalazłem 'MemoryCache' w' System.Runtime.Caching' nazw że wygląda idealnie. Zastrzeżenie, że mogę stracić dane, jeśli App Recover jest w porządku, ponieważ próbuję zapobiec ponownemu wywołaniu bazy danych w * każdym * wywołaniu API. Używanie 'MemoryCache.Get()' i 'MemoryCache.Add()' wydaje się działać dobrze dla mnie. 'AddOrGetExisting()' wyglądało fajnie, ale nie działało dla mojej sytuacji; nadal wymagałoby pobierania danych z DB przed wywołaniem. Ustawiłem "AbsoluteExpiration" na 30 minut. – atconway

+5

Tak jak znacznik, który pomaga ludziom po drodze, zalecaną technologią buforowania na Azure jest teraz Redis. Redis lub inna rozproszona pamięć podręczna jest wymagana, jeśli masz więcej niż 1 wystąpienie swojego API. Azure Managed Cache jest teraz bardzo ukryty, dostępny tylko z Powershell. Po prostu go tam trzymają, aby pomóc ludziom, którzy wcześniej go używali. –

+0

Redis jest zbyt kosztowny, jeśli wszystko, co robisz, polega na buforowaniu kilku wywołań danych WebApi. –

31

Rozwiązanie, które udało mi się zastosować, dotyczyło przestrzeni nazw MemoryCache w przestrzeni System.Runtime.Caching. Oto kod, który zakończył się pracuje dla buforowania moją kolekcję:

//If the data exists in cache, pull it from there, otherwise make a call to database to get the data 
ObjectCache cache = MemoryCache.Default; 

var peopleData = cache.Get("PeopleData") as List<People>; 
if (peopleData != null) 
    return peopleData ; 

peopleData = GetAllPeople(); 
CacheItemPolicy policy = new CacheItemPolicy {AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(30)}; 
cache.Add("PeopleData", peopleData, policy); 
return peopleData; 

Oto kolejny sposób znalazłem używając Lazy<T> wziąć pod blokadą konta i współbieżności. Razem zasługa tego postu: How to deal with costly building operations using MemoryCache?

private IEnumerable<TEntity> GetFromCache<TEntity>(string key, Func<IEnumerable<TEntity>> valueFactory) where TEntity : class 
{ 
    ObjectCache cache = MemoryCache.Default; 
    var newValue = new Lazy<IEnumerable<TEntity>>(valueFactory);    
    CacheItemPolicy policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(30) }; 
    //The line below returns existing item or adds the new value if it doesn't exist 
    var value = cache.AddOrGetExisting(key, newValue, policy) as Lazy<IEnumerable<TEntity>>; 
    return (value ?? newValue).Value; // Lazy<T> handles the locking itself 
} 
+1

jak nazwać tę metodę GetFromCache ?, czego potrzebuję paas w parametrze valueFactory? Jeśli muszę przechowywać wyjście Get, które wywołuje repozytorium, jak z niego korzystać, a następnie użyć go w kolejnym wywołaniu? – F11