cache an object once for all users, refresh every 30 minutes - c#

I'm working on an intranet and I'd like to cache an object on the server and serve that up to users when requested, as opposed to having each user generate their own copy of the object. I'd also like to refresh the object every 30 minutes...
I'm currently using HttpContext.Current.Cache, but I'm unsure if:
1. that's what I'm looking for
2. there's a better way to do this (I'm thinking web service)?
Thank you.

HttpContext.Current.Cache is appDomain wide cache shared between all users. It is appropriate place for your case to store whatever objects you need to share across all users. It also supports expiration.

Using HttpRuntime.Cache (same as HttpContext.Cache) has the pitfall in that it's tied to the AppDomain. When that recycles so does your cache.
Instead install something like Membase (Memcache) which acts as an external cache provider and will be persistent between application recycles.
As to refreshing, personally I would cache the item for 30 minutes but allow it to expire. Only refresh it when a request comes in and the item is no longer in the cache. This keeps the cache efficient in that only requested objects remain in the cache.
As a shameless plug I wrote a cache library a while ago that supports Memcache which you can use, see here - http://www.lloydkinsella.net/2012/09/30/bettering-the-better-net-cache/

Related

How to cache an object without user interruption?

This is easier to explain if I first explain my order of events:
User requests a webpage that requires x database objects
The server checks the cache to see if it is cached, and if it is not, it re-requests the database
The page is sent to the user
My issue is, when the user requests a webpage and the cache is expired, it will take a very long time for the cache to update. The reason is because the data that is being cached includes data fetched from other locations, so web requests are being made to update the cache. Because it is making web requests, it can take quite a while for the cache to update, causing the user's webpage to sit there and load for upwards of ten seconds or more.
My question is, how would I go about reducing or completely removing these edge cases where, when the cache is updating, the user's webpage takes forever to load?
The first solution I came up with was to see if I could persist the MemoryCache past its expiration time, or at the very least check its expiration time, so that I can fetch the old object and return that to the user, and then initiate a cache update in another thread for the next user. However, I found that MemoryCache completely removes the items entirely upon expiration (which makes sense), and that there is no way to avoid doing this. I looked into using CacheItemPriority.NeverRemove, but there is no way to check the expiration time (for some weird reason).
So the second solution I came up with was to create my own cache, but I don't know how I would go about doing that. The object I am storing is a list objects, so I would prefer to avoid a wrapper object around them (but, if that's what I have to do, I'll be willing to do that). I would like this cache to be abstract, of course, so it can handle any type of item, and using a wrapper object for lists would not allow me to do that.
So what I'm looking for in a custom cache is:
Ability to check expiration date
Items are not removed upon expiration so that I can manually update them
Yet through the past couple of hours searching online, I have found nothing that describes a cache that's even remotely close to being able to do something like this (at least, one that's provided with .NET Core or available in the NuGet packages). I have also not found a guide or any examples that would help me understand how to create a custom cache like this.
How would I go abouts making this custom cache? Or is a cache even what I'm looking for here?

Web api cache architecture

Net web api developer and i want to know if im working correctly.
Im saving a changeable objects into the cache.
Other developers on my team said only static data should be stored in the cache.
So i wanted to know if only static data need to be store in cache or there's another right way to do it.
Thanks.
I use caching for changeable objects because they take a reasonable amount of time to generate, although the frequency of their changing varies.
There are a couple of things which I do to try and make sure the data is always valid.
On the cached item I put a policy which will keep the item in cache for say 15 minutes, and make the expiration time sliding. This keeps the used items in cache but drops less used items.
I also have cache eviction end points on the API, and the process which updates the data in the database calls the endpoint once the process has been complete. The items which have been updated are then removed from the cache and hence rebuilt the next time they are requested.
In the end I think it all boils down to how long it takes to get the object you are trying to return, and whether the delay to generate it is acceptable.

(ASP.NET Cache API) Is it possible that an item may be removed from cache before its set expiry?

I've been tasked with implementing server-side cache on a web application to improve performance of the front-end. The objective is to cache a large dataset resulting from an MDX query on an SSAS cube. The cache is to expire at midnight, which is when the cube is processed each day. I've decided to use the Cache.NET API, and so I have this:
Cache.Insert("MDXResult", myMDXDataSetThatExpiresAtMidnight, null,
DateTime.Now.AddMinutes(getMinutesUntilMidnight()), TimeSpan.Zero);
What troubles me is something I read on the MSDN page on ASP.NET Caching: Techniques and Best Practices:
The simplest way to store data in the Cache is simply to assign it,
using a key, just like a HashTable or Dictionary object:
Cache["key"] = "value";
This will store the item in the cache without any dependencies, so it
will not expire unless the cache engine removes it in order to make
room for additional cached data.
The last bit -- the fact that the cache engine removes cached data in order to make room for additional cached data -- does it apply to only the case above where the item is stored in cache without any dependencies? How can I be sure that the cache of myMDXDataSetThatExpiresAtMidnight will not be cleared by the cache engine before its expiry time?
Alternatively, is there any way to control the amount of space allocated for server-side cache, such as a setting in web.config or similar, to ensure that cache isn't inadvertently cleared?
All entries, including those with dependencies, can be removed at any time. The dependencies just help the cache engine calculate when items have expired.
You can not enforce your item to stay in the cache in any way. The cache may remove it for known, unknown and other causes. Usually due to expiration (time or dependency based) or memory pressure. You can, however, use the Cache.Add overload which accepts an CacheItemRemovedCallback onRemoveCallback which may be a function that calculates a new item (or knows of the old one) and add it again. I'm not sure about the actual timings, but I guess that there is a brief time where the item is not in the cache, while your callback is executed and has not yet added the new item.
You can configure the caching using the CacheSection in web.config.

Using cache in ASP.NET

I'm trying to use the cache in an ASP.NET MVC web application to store some list data that rarely updates. I insert this data into the cache in an UpdateCache() method like this:
HttpContext.Current.Cache.Insert("MyApp-Products", products, null, DateTime.Now.AddYears(99), Cache.NoSlidingExpiration);
Then in my model I retrieve it:
public static List<string> GetProducts()
{
var cachedProducts = HttpContext.Current.Cache["MyApp-Products"];
if (cachedProducts == null)
{
UpdateCache();
cachedProducts = HttpContext.Current.Cache["MyApp-Products"];
}
return ((List<string>)cachedProducts );
}
The first time I visit the page, UpdateCache() is called as expected. If I refresh, the data comes from the cache and I do not need to call UpdateCache(). However, after maybe 15 mins, I come back to the app and the cached values are gone. My understanding was that this cache was per application, not session, so I would have expected it to still be there for myself or another user.
Is there something wrong with the way I'm storing the cache? Or is there something I'm not understanding about how the Cache in ASP.NET works in a web app?
My understanding was that this cache was per application, not
session, so I would have expected it to still be there for myself or
another user.
While the cache is per application, ASP.NET doesn't provide you any guarantees that if you stored something into the cache you will find it back there. The cache could be evicted under different circumstances such as for example your server starts running low on memory and so on. You can subscribe to an event and get notified when an item is evicted from the cache. You can also define a priority when caching an item. The higher the priority, the lower the chance of this item getting evicted.
Also since the cache is stored in the memory of the web server (by default) you should not forget the fact that your application domain could be recycled at any point by IIS. For example after a certain amount of inactivity or if it starts running low on memory or even if a certain CPU threshold usageis reached, ... and everything that is stored in the memory including the cache will simply disappear into the void and the next request in your application will start a new AppDomain.
But in any cases make sure that you check if the item is present in the cache before using it. Never rely on the fact that if you stored something into it, you will find it.
All this blabla to come to the really essential point which is something very worrying with your code. It looks like you are storing a List<string> instance into the cache. But since the cache is per application, this single instance of List<string> could be shared between multiple users of the application and of course this could happen concurrently. And as you know List<T> is not a thread safe structure. So with this code you will, at best, get an exception and at worst you will get corrupt data. So be very careful what you are caching and how you are synchronizing the access to the structure especially if you are caching a non thread-safe class.
IF this is on a full IIS, and happens around every 15minuntes. Remember to check the Idle timeout value.
That being said, if this list "never" changes, why not store it in a static array instead.
I can see how storing data in general in database is better than in static object.
For one, in case data does change, it is easier to update DB than the application.
Try explicitly setting absolute expiration when caching your object:
HttpRuntime.Cache.Insert("MyApp-Products", cachedProducts, null, DateTime.Now.AddDays(20), TimeSpan.Zero );
Note HttpRuntime is used instead of HttpContext for performance reasons even though the difference is minor.

Saving Values in Session or Cache - Difference? ASP.NET

I'd like to know when exactly I should use the Session and when exactly I should use the cache. Are there differences in performance? Can one of them handle a lot of data better? Should the Cache only be used for stuff that's associated with the Application whilst the Session should only be used for stuff that's associated with the current session/user?
Is it wiser to save values which I received from a DB in the Session or the Cache - is there a difference at all assuming I make the cache-keys unique? E.g. Cache["MyKey"+UserId.ToString()].
Also, in general, is using the Session/Cache a lot wiser than retrieving Data from a DB or a Webservice or is there a limit of data that'll be retrieved quicker?
Some differences between session and cache:
The session is per user while the cache is per application
You can store the session data out-of-process (SessionServer or SqlServer) e.g. when using a web farm
What you put into the session stays there until the session is terminated/abandoned or times-out
With the cache, you can specify that items are automatically removed after some time (absolute) or after they were not accessed for some time (sliding)
You can also use SqlCacheDependencies to have items removed from the cache when some data changes in a database
the ASP.NET runtime will also automatically remove items from the cache if the available memory gets low
As for performance:
As long as you use InProc session state, I guess there won't be any performance difference between session and cache.
As soon as you use external session state, performance will obviously be lower than the InProc-cache but I don't have any numbers (depends on network, SQL server power, etc).
BTW: there are also distributed caching solutions which allow having an external, shared cache (similar to the out-of-process session state).

Categories