Cache data returned by stored procedures? - asp.net

I have an Asp.Net MVC 3 site. The following is the call stack
Web page/jQuery: $(document).Ready(.... Ajax calls... render the page...)
=> MVC Control methods
=> Entity framework 4.1
=> mapped store procedures (SQL Server 2008)
Question:
Where is the best place to implement cache?
How to let the page know that the underline SQL server tables have been updated?

Not sure about the "best" way to do it but one way to do it would be to have an MVC controller action which calls to the db to check and see if the data has been updated. (You can do it by time-stamp.)
The resulting function will then retreive the data from cache or from the server.
http://davidwalsh.name/cache-ajax
The only interesting thing to note however; is that you should make sure that the call to first find out if you can use cached content is faster than not caching content at all.

Try to add caching as close to the source as possible. This way more of your app could gain benefits from the improved speed.
If you control the code that is modifying the underlying tables you could invalidate the cache from there. You could also place a short timeout on your cache. If its a heavily used query caching it only a second could increase speed many fold. Make sure to test the performance gain so that you can tweak timeouts.

For question #2, you may want to look into Query Notifications. Setting everything up is a bit complicated, but that will enable you to do things such as caching until the data in your database has been updated.

One way is to cache rendered views some specified time.
Let's say that you have page that is not updated often. So instead of hitting database on every visit you can store rendered view in cache. This is achieved using OutputCaching - http://www.asp.net/mvc/tutorials/improving-performance-with-output-caching-cs.
Another way could be to store data.
Here again You can cache it for some specified time. In ASP.NET (MVC) it can be achieved using Cache object - http://msdn.microsoft.com/en-us/library/aa478965.aspx.
Cache object let's you specify how long data is to be cached when You put it in cache. For example:
Cache.Insert("key",
myTimeSensitiveData,
null,
DateTime.Now.AddMinutes(1),
TimeSpan.Zero);
Or you can cache until it is 'invalidated'.
Say you have GetCustomers and UpdateCustomer methods. In GetCustomers you check if data is in Cache. If not you hit the database, put it in cache and return. It is in cache until someone calls UpdateCustomer. In that method you write modified customer to database and invalidate data stored in Cache. You can just remove it. That way when GetCustomers is called again it will hit the database and populate Cache again. But remember that Cache has global scope and is accessible for many threads at the same time. You will need some synchronization code around access to Cache.

Related

Synchronizing local cache with external application

I have two separate web applications:
The "admin" application where data is created and updated
The "public" application where data is displayed.
The information displayed on the "public" changes infrequently, so I want to cache it.
What I'm looking for is the "simplest possible thing" to update the cache on the public site when a change is made in the admin site.
To throw in some complexity, the application is running on Windows Azure. This rules out file and sql cache dependencies (at least the built in ones).
I am running both applications on a single web role instance.
I've considered using Memcached for this purpose. but since I'm not really after a distributed cache and that the performance is not as good as using a memory cache (System.Runtime.Caching) I want to try and avoid this.
I've also considered using NServiceBus (or the Azure equivalent) but again, this seems overkill just to send a notification to clear the cache.
What I'm thinking (maybe a little hacky, but simple):
Have a controller action on the public site that clears the in memory cache. I'm not bothered about clearing specific cached items, the data doesn't change enough for me to worry about that. When the "admin" application makes a cache, we make a httpwebrequest to the clear cache action on the public site.
Since the database is the only shared resource between the two applications, just adding a table with the datetime of the last update. The public site will make a query on every request and compare the database last update datetime to one that we will hold in memory. If it doesn't match then we clear the cache.
Any other recommendations or problems with the above options? The key thing here is simple and high performance.
1., where you have a controller action to clear the cache, won't work if you have more than one instance; otherwise, if you know you have one and only one instance, it should work just fine.
2., where you have a table that stores the last update time, would work fine for multiple instances but incurs the cost of a SQL database query per request -- and for a heavily loaded site this can be an issue.
Probably fastest and simplest is to use option 2 but store the last update time in table storage rather than a SQL database. Reads to table storage are very fast -- under the covers it's a simple HTTP GET.
Having a public controller that you can call to tell the site to clear its cache will work as long as you only have one instance of the main site. As soon as you add a second instance, as calls go through the load balancer, your one call will only go to one instance.
If you're not concerned about how soon the update makes it from the admin site to the main site, the best performing and easiest (but not the cheapest) solution is to use the Azure AppFabric Cache and then configure it to use a a local (in memory) cache with a short-ish time out (say 10 minutes).
The first time your client tries to access an item this would be what happens
Look for the item in local cache
It's not there, so look for the item in the distributed cache
It's not there either so load the item from persistent storage
Add the item to the cache with a long-ish time to live (48 hours is the default I think)
Return the item
Steps 1 and 2 are taken care of for you by the library, the other bits you need to write. Any subsequent calls in the next X minutes will return the item from the in memory cache. After X minutes it falls out of the local cache. The next call loads it from the distributed cache back into the local cache and you can carry on.
All your admin app needs to do is update the database and then remove the item from the distributed cache. The next time the item falls out of the local cache on the client, it will simply reload the data from the database.
If you like this idea but don't want the expense of using the caching service, you could do something very similar with your database idea. Keep the cached data in a static variable and just check for updates every x minutes rather than with every request.
In the end I used Azure Blobs as cache dependencies. I created a file change monitor to poll for changes to the files (full details at http://ben.onfabrik.com/posts/monitoring-files-in-azure-blob-storage).
When a change is made in the admin application I update the blob. When the file change monitor detects the change we clear the local cache.

Caching user data in asp.net application

What's the best way to cache web site user data in asp.net 4.0?
I have a table of user settings that track all kinds of user or session specific stuff like the state of UI elements (open/closed), preferences, whether some dialog has been dismissed, and so on. Since these don't change very often (for each user, anyway) but are looked up frequently it seems sensible to cache them. What's the best way? These are the options I've identified...
Store them in HttpContext.Current.Session directly (e.g. Session["setting_name"])
Store them in HttpContext.Current.Cache
Use a global static dictionary, e.g. static ConcurrentDictionary<string,string> where the key is a unique userID + setting name value
Store a dictionary object for each session in Session or Cache
What's the most sensible way to do this? How does Session differ from Cache from a practical standpoint? Would it ever make sense to store a dictionary as a single session/cache object versus just adding lots of values directly? I would think lookups might be faster, but updates would be slower since I'd have to re-store the entire dictionary when it changed.
What problems or benefits might there be to using a global static cache? Seems like this would be the fastest, but I'd have to manage the size. I could just flush it periodically if it hits a certain size, or keep a cross reference queue and remove things oldest first when it gets to a certain size. Does this make any sense or is it just trying too hard?
Session may end up being stored out-of-process or in a database, which can make retrieving it expensive. You would likely be using a session database if your application is to be hosted in a server farm, as opposed to a single server. A server farm provides improved scalability and reliability, and it's often a common deployment scenario. Have you thought about that?
Also, when you use Session not in-process, it ends up getting serialized to be sent out-of-process or to a database, and deserialized when retrieved, and you are effectively doing what you describe above:
... updates would be slower since I'd have
to re-store the entire dictionary when
it changed. ...
.. since, even if you use individual session keys, the entire Session object for a user is serialized and deserialized together (all at once).
Whereas, Cache would be in memory on a particular server in the farm, and therefore much more efficient than going out of process or to the database. However, something in cache on one server might not be in cache on another. So if a user's subsequent request is directed to another server in the farm, the cache on that server might not yet hold any of the user's items.
Nevertheless, I'd suggest you use Cache if you're caching for performance reasons.
p.s. Yes, you're trying too hard. Don't reinvent the wheel unless you really need to. :-)
might be better to put your information into memcached for scalability

How to cache a List of objects in ASP.NET

I have a List of objects in an asp.net page. when the page loads in the browser for the first time, I fetch data from the database, create objects with those data and populate the list. All these are done inside the page load event handler. Now when the page is posted back to the page, the previous list is gone, since the variables were all freed.
How can I cache that List, so that when this page is posted back, all my objects are available?
As #Eilon asked, is this data user-specific or is it site specific?
If the data is user specific you can use the Session State to store it, however it will expire when the users session ends, and in some cases can still invoke a roundtrip to your database server (if for instance it is backed by SQL server instead of being in-proc, etc).
If the data is application wide you can also use the Application Cache. It is site wide, resides in the process domain and is therefore available to everyone who has sessions on that server. Special care must be taken when using this in a multi-server scenario, but it is easily doable.
It should be noted that the Application Cache (and any other global setup) can make your app load slow for the first user to hit the site if the setup takes time. IIS7 and ASP.NET have attempted to address this with a module released recently that periodically wakes your app up to ensure that the global cache is either pre-populated, or remains alive.
Use Cache.Add(key_name, list_object, ...) to save the list, and then Cache[key_name] to retrieve it (you will need to cast the retrieved object to the appropriate type). The Add method has several more parameters to specify if and when the cached object expires.
The Cache object is actually System.Web.Caching.Cache and is accessible from your aspx page, or as HttpContext.Current.Cache.
if it's only relevant for this page, i would use the ViewState.
The syntax is familiar if you used sessionstate before:
to set:
ViewState["Persons"] = new List<Person>();
to read
List<Person> persons = ViewState["Persons"] as List<Person>;
The viewstate data is only kept for this page, but is sent as (serialized) text with your page, so don't use it for 1000 Persons because your page will be a very large download .
If you have lots of data, you're better of using the Cache object, but only if you're not on a web farm and remember to clear the data once in a while when you no longer need the data and use a cache key per user if it is per user data.
Last you can use the Session state, it is a per-user store, but remember to clear the data once in a while when you no longer need the data.
So, a lot to choose from depending on the situation.
Michel
use HttpContext.Current.Session.
To add to GrayWizard's answer, you can use viewstate too, but since it's included in postbacks, make sure you're not persisting something that takes up alot of space or needs to be secure since it's not encrypted by default.
Here's an overview - it's dated, but still relevant.
http://msdn.microsoft.com/en-us/magazine/cc300437.aspx

Is there conditional caching in ASP.NET?

Is there a built-in asp.net way to conditionally serve pages, for example I want the following logic:
If there is a session data I generate
a page, if there is no session data I
serve the cached page.
I am only interested in knowing about a built-in asp.net mechanism for this. If it does not exist I am probably going to simply cache my page manually and decide whether to serve it or not for each request, based on the session data availability.
I don't think there is built-in support (like varyByParam) for generating fresh output for users with Session Data.
As you suggest, I would recommend manually caching the pages. I would probably determine the user's Session state in the PreRequestHandlerExecute event handler in the Global.asax and then maybe set:
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
At the risk of karmabombing, I really don't like this approach to caching.
For me if a GET request is made, then a server should respond to that in good faith. Caching at a page level should be controlled by http headers because the primary goal is not to get the redundant request at all - you don't want to allocate server/bandwidth resources full stop.
Caching objects which are resources involved in making up a page I can totally get behind, but I can't see great arguments for caching a page wholesale.
Respect the headers.
You might want to look at the substitution control (Link) new in .NET 2.0, however it might not be exactly what you are after.

Caching the profiles from SqlProfileProvider -- ProfileManager.GetAllProfiles result

I'm using the SqlProfileProvider on one of my websites and in one page I need to fetch the whole list of profiles (it is an intranet).
The method that I use is the ProfileManager.GetAllProfiles(). The problem is that its performance is really bad and it slows down the website considerably.
Therefore, I was thinking of caching the result of the method call in the Application scope as a DataTable (so I could filter/search on it as well).
My problem is that I have several servers running this webapp, and I would like the cache to be in sync. I started using memcached but I was put off by some problems (hence going back to thinking in caching in the Application scope).
So, here are my questions:
Would it be efficient to store the DataTable containing the profiles in the Application object? Or, is it possible to store objects in the Cache and have them available for all clients/browsers?
Is it possible to add a (SQL) Cache Depedency to this cache?
You could cache portions of the web page which will depend on the list of profiles by putting them in a user control and marking it as cacheable. SqlCacheDependency cache policy expiration could be defined as well. As for the cache location, every web server in the farm will have it's own version in memory but using cache expiration will make sure that this version is not out of sync with the data in the DB.
Page or fragment caching is the most effective caching technique because contrary to caching your model (a DataTable or whatever) you don't pay the price of HTML rendering.

Resources