Keeping a large volume of data in Session - Suggestions / alternatives? - asp.net

I'm developing a web app for which the client wants us to query their data as little as possible. The data will be coming from a Microsoft CRM instance.
So we've agreed that data will only be queried as and when it is needed, therefore if a web user wants to see a list of contacts (for example) that list is fetched into a local DataTable. Then if a new contact is created on the website the new contact is sent to CRM and added to the local DataTable at the same time. Likewise for edits.
If the user then looks at their contacts again the data will just come from the local DataTable.
At the moment local data is being kept in Session but my concern is that too much memory will start being used up. However traffic is expected to be pretty small, perhaps no more than 20 concurrent users so am I worrying about nothing or is there a better way you can suggest to handle this?

You worry about nothing. Basically it is a scalability dump - stupid desig. BUT: if you can throw 1gb of memory at the problem, for 20 users, storing 16mb of memory is not a problem.
The main problem starts when pepople count grows and the application needs to be rewritten.

20 concurrent users is not too many.
Clients "looks at their contacts": Depending on "contacts" table size, could you consider storing it in in-memory dataset( all contacts). You could then filter acc to primary key.
Alternative to session:Cache, Application
Cache with SqlCacheDependency and CacheItemRemovedCallback should be a good option to session.
XML files for each customer contacts.

Related

NoSQL and AppFabric with Azure

I have an ASP.net application that I'm moving to Azure. In the application, there's a query that joins 9 tables to produce a user record. Each record is then serialized in json and sent back and forth with the client. To increase query performance, the first time the 9 queries run and the record is serialized in json, the resulting string is saved to a table called JsonUserCache. The table only has 2 columns: JsonUserRecordID (that's unique) and JsonRecord. Each time a user record is requested from the client, the JsonUserCache table is queried first to avoid having to do the query with the 9 joins. When the user logs off, the records he created in the JsonUserCache are deleted.
The table JsonUserCache is SQL Server. I could simply leave everything as is but I'm wondering if there's a better way. I'm thinking about creating a simple dictionary that'll store the key/values and put that dictionary in AppFabric. I'm also considering using a NoSQL provider and if there's an option for Azure or if I should just stick to a dictionary in AppFabric. Or, is there another alternative?
Thanks for your suggestions.
"There are only two hard problems in Computer Science: cache invalidation and naming things."
Phil Karlton
You are clearly talking about a cache and as a general principle, you should not persist any cached data (in SQL or anywhere else) as you have the problem of expiring the cache and having to do the deletes (as you currently are). If you insist on storing your result somewhere and don't mind the clearing up afterwards, then look at putting it in an Azure blob - this is easily accessible from the browser and doesn't require that the request be handled by your own application.
To implement it as a traditional cache, look at these options.
Use out of the box ASP.NET caching, where you cache in memory on the web role. This means that your join will be re-run on every instance that the user goes to, but depending on the number of instances and the duration of the average session may be the simplest to implement.
Use AppFabric Cache. This is an extra API to learn and has additional costs which may get quite high if you have lots of unique visitors.
Use a specialised distributed cache such as Memcached. This has the added cost/hassle of having to run it all yourself, but gives you lots of flexibility in the long run.
Edit: All are RAM based. Using ASP.NET caching is simpler to implement and is faster to retrieve the data from cache because it is on the same machine - BUT requires the cache to be populated for each instance of the web role (i.e. it is not distributed). AppFabric caching is distributed but is also a bit slower (network latency) and, depending what you mean by scalable, AppFabric caching currently behaves a bit erratically at scale - so make sure you run tests. If you want scalable, feature rich distributed caching, and it is a big part of your application, go and put in Memcached.

ASP.Net SQLServer Session State Versus Direct Database Access

On the website I am developing, I have a number of "user preferences" that I keep stored for my returning, registered users (for example, the number of product summaries per page to display). I am curious if there is any performance benefit to storing/retrieving this data in an ASP.Net SQLServer Session State versus retrieving it as-needed directly from my database. Many thanks in advance!
Its always better to store Data in Session State (performance point of view), as long as the data isn't too Huge. This way, you Production Data Database (where you persist your UserData) Hits would reduced. Just make sure that User Wouln't change his preferences which are cached in session.
Only potential problem with session is that Session is maintained per User. so, if there are too many users on your website, session state grows but since you are using SQL Server as you Session Store, you are good on that. Had you been using InProc SessionMode, your Session would have been in memory (a critical resource on production servers!)
You are taking the hit going to sql server anyways. So you shouldn't have a noticeable performance impact and also if using sql server for session state - you don't have to worry much about the implementation details - hence could be a 'bit' easier to use. But no - there is no main benefit. one could argue it depends on how you store/lookup your information but for most apps the difference here is absolutely negligible - it's up to you how you want to implement. Now if you ever move away from sql server session state then you have another set of issues to be concerned over (app resets, etc) but thats not in the scope of what you asked : )

using sessions: am I abusing it?

Let's say I have a site where a reporting page will contain user-specific daily reports.
By default, the user lands on today's report but then if he clicks on a calendar control and selects a new date, a new report will load for that day. What I want to do is use sessions as a cache for reports. The first time he loads a report for a day, it's loaded from the database into the session and then from the session to the page. Each time he loads a new report for a date, the logic first checks to see if this particular report is in the session and only if it's not is it loaded from the DB. A report has about 15 columns and is made up of about 300-500 rows per day. What will be stored in the session is a dictionary of lists of objects, with the date as the key and the list as the value. I'm using InProc session. I'm also considering storing several other dictionaries as well for other lists of objects.
Is this an efficient way to make the most of the .net framework? If it doesn't actually improve performance over making calls to the data source, will it make it slower? I'm looking to build something that'll scale to about 500-1000 simultaneous users or so.
Thanks.
It sounds like your pre-optimizing to me. Have you run any performance tests to verify that you get any benefit at all to putting it in Session (or Cache)?
Have your users expressed concern over the performance?
For me, I wouldn't consider optimizing to any kind of cache until I knew I had a performance issue, and then I would look at why I had the performance problem, and optimize that
There are striking differences between cache and session state:
Cache is server-based but session is user-based (can be across multiple servers)
Cache is usually URL-based so if the URL is the same for all users, this cannot be implemented via cache.
Cache will be recycled and memory reclaimed when server is close to out of memory (so you will not get an OutOfMemory exception using cache) but session just grows and you will get an OutOfMemory if you are using in-process sessions and not.
Session is usually used for user level state that has to be stored but cache is meant for performance boosting.
With all above, and considering your requirement, you had better use cache unless the URL is the same for all users. If you are using session state, you need to be very careful as just a little performance nicety can kill your website.

What is the best way to manage one's session variables?

In my .NET web app, I keep basic user info in a user session object. I also usually keep a director class in the session; which is basically just has info about whatever thing it being worked on on that screen (like a customer id).
I am trying to keep from adding a ton of sessions. I also want to make sure at any given time ONLY the sessions that are necessary are in memory.
This means I need an effective way of managing my session variables. Any suggestions?
Two things:
1 - You should not be storing so much in session that managing memory is a concern. I.e., don't store objects in session, store pointers to things, e.g., rather than an instance of User just store the UserID. If you need to, you can add caching of retrieval of info, but that should be in a caching layer separate from sessions.
2 - Use database sessions, so that there is no concern about server memory, and so that you can add more web servers easily if desired (note, StateServer gives you this capability as well). Additionally, this lets you recycle the app pool without users losing their session. This is the main reason I do it - it lets me deploy on the fly.
The reason to treat sessions so delicately, is that they hang around after a user's last request, typically for 10 to 20 minutes. So, requests from many different sessions can use up large amounts of server memory if you are storing large objects in session. Doing even crazier things, like storing database connections in session, can result in you using up all available database connections, just because so many are hanging around in memory waiting for the session to expire.
Ideally, there is no "managing" of sessions required.
What I normally do is only keep the id of an object in Session and keep the data in a caching layer in front of the database. That way, you keep your session fairly small but most data can still be retrieved efficiently if the item is in cache. This has usually worked well for me.
I think you're misunderstanding sessions in ASP.NET. You do not explicitly manage them (although you could, you would rarely want to) they are implicitly created and destroyed by ASP.NET and IIS. Every user is given a session.
Now anything you store inside a users session is stored in memory on the server so if you routinely place large objects in each users sessions this will cause the memory to grow rapidly leading to performance and scalability issues.
The only data you need to store in the session is transient data that you want to be available across different page requests that you want to be secured that it is not available to the client in a cookie or similar construct.
However reading what you're doing this is most likely not needed. Since you are working with a specific page and "director" functionality this would most likely be fitting to place on the page in the viewstate as an intermediary data store.
There is no wright answer. It depends on the number of concurrent users, on the size of your memory.
Keeping things on session is faster than on a database, if you have your session variables in proc.
I usually try to keep just things that I know the user might need during a specific task, or, like you said, information of the current user.
My suggestion is:
Wrap the session access into a IPerSessionCache interface
Have a concrete implementation of this interface
Use an instace of the concrete class in the code to get/set session data
By this, then you have the freedom to clean up the instance of IPerSessionCache when the session ends
The code will not need to know where the IPerSessionCache actually stores the data (ie. it could in the Session or in a database or in a cookie etc.)
You would have better control on the lifetime of the IPerSessionCache especially if you use a DI container for managing & creating the instance
HTH.
My suggestion: Don't use session variables. Store everything in a database.

What to put in a session variable

I recently came across a ASP 1.1 web application that put a whole heap of stuff in the session variable - including all the DB data objects and even the DB connection object. It ends up being huge. When the web session times out (four hours after the user has finished using the application) sometimes their database transactions get rolled back. I'm assuming this is because the DB connection is not being closed properly when IIS kills the session.
Anyway, my question is what should be in the session variable? Clearly some things need to be in there. The user selects which plan they want to edit on the main screen, so the plan id goes into the session variable. Is it better to try and reduce the load on the DB by storing all the details about the user (and their manager etc.) and the plan they are editing in the session variable or should I try to minimise the stuff in the session variable and query the DB for everything I need in the Page_Load event?
This is pretty hard to answer because it's so application-specific, but here are a few guidelines I use:
Put as little as possible in the session.
User-specific selections that should only last during a given visit are a good choice
often, variables that need to be accessible to multiple pages throughout the user's visit to your site (to avoid passing them from page to page) are also good to put in the session.
From what little you've said about your application, I'd probably select your data from the db and try to find ways to minimize the impact of those queries instead of loading down the session.
Do not put database connection information in the session.
As far as caching, I'd avoid using the session for caching if possible -- you'll run into issues where someone else changes the data a user is using, plus you can't share the cached data between users. Use the ASP.NET Cache, or some other caching utility (like Memcached or Velocity).
As far as what should go in the session, anything that applies to all browser windows a user has open to your site (login, security settings, etc.) should be in the session. Things like what object is being viewed/edited should really be GET/POST variables passed around between the screens so a user can use multiple browser windows to work with your application (unless you'd like to prevent that).
DO NOT put UI objects in session.
beyond that, i'd say it varies. too much in session can slow you down if you aren't using the in process session because you are going to be serializing a lot + the speed of the provider. Cache and Session should be used sparingly and carefully. Don't just put in session because you can or is convenient. Sit down and analyze if it makes sense.
Ideally, the session in ASP should store the least amount of data that you can get away with. Storing a reference to any object that is holding system resources open (particularly a database connection) is a definite scalability killer. Also, storing uncommitted data in a session variable is just a bad idea in most cases. Overall it sounds like the current implementation is abusively using session objects to try and simulate a stateful application in a supposedly stateless environment.
Although it is much maligned, the ASP.NET model of managing state automatically through hidden fields should really eliminate the majority of the need to keep anything in session variables.
My rule of thumb is that the more scalable (in terms of users/hits) that the app needs to be, the less you can get away with using session state. There is, however, a trade-off. For web applications where the user is repeatedly accessing the same data and typically has a fairly long session per use of the site, some caching (if necessary in session objects) can actually help scalability by reducing the load on the DB server. The idea here is that it is much cheaper and less complex to farm the presentation layer than the back-end DB. Of course, with all things, this advice should be taken in moderation and doesn't apply in all situations, but for a fairly simple in-house CRUD app, it should serve you well.
A very similar question was asked regarding PHP sessions earlier. Basically, Sessions are a great place to store user-specific data that you need to access across several page loads. Sessions are NOT a great place to store database connection references; you'd be better to use some sort of connection pooling software or open/close your connection on each page load. As far as caching data in the session, this depends on how session data is being stored, how much security you need, and whether or not the data is specific to the user. A better bet would be to use something else for caching data.
storing navigation cues in sessions is tricky. The same user can have multiple windows open and then changes get propagated in a confusing manner. DB connections should definitely not be stored. ASP.NET maintains the connection pool for you, no need to resort to your own sorcery. If you need to cache stuff for short periods and the data set size is relatively small, look into ViewState as a possible option (at the cost of loading more bulk onto the page size)
A: Data that is only relative to one user. IE: a username, a user ID. At most an object representing a user. Sometimes URL-relative data (like where to take somebody) or an error message stack are useful to push into the session.
If you want to share stuff potentially between different users, use the Application store or the Cache. They're far superior.
Stephen,
Do you work for a company that starts with "I", that has a website that starts with "BC"? That sounds exactly like what I did when I first started developing in .net (and was young and stupid) -- I crammed everything I could think of in session and application. Needless to say, that was double-plus ungood.
In general, eschew session as much as possible. Certainly, non-serializable objects shouldn't be stored there (database connections and such), but even big, serializable objects shouldn't be either. You just don't want the overhead.
I would always keep very little information in session. Sessions use server memory resources which is expensive. Saving too many values in session increases the load on server and eventualy the performance of the site will go down. When you use load balance servers, usage of session can run into problems. So what I do is use minimal or no sessions, use cookies if the information is not very critical, use hidden fields more and database sessions.

Resources