I am designing a web API which requires fast read only access to a large dataset which will be hopefully be constantly stored and ready for access. Access will be from a static class which will just do some super fast lookups on the data.
So, I want to pre-cache a Dictionary<string,Dictionary<string,Dictionary<string,myclass>>>, with the total number of elements at the third level dictionary being around 1 Million, which will increase eventually, but lets say not more than 2 million ever. 'myclass' is a small class with a (small) list of strings, an int, an enum and a couple of bools, so nothing major. It should be a bit over 100mb in memory.
From what I can tell, the way to do this is simply call my StaticClass.Load() method to read all this data in from a file with the Application_Start event in Global.asax.
I am wondering what the things I need to consider/worry about with this. I am guessing it is not just as simple as calling Load() and then assuming everything will be OK for future access. Will the GC know to leave the data there even if the API is not hit for a couple of hours?
To complicate things, I want to reload this data every day as well. I think I'll just be able to throw out the old dataset and load the new one in from another file, but I'll get to that later.
Cheers
Please see my similar question IIS6 ASP.NET 2.0 Application Cache - data storage options and performance for large amounts of data BUT in particular the answer from Marc and his last paragraph about options for large cache's which I think would apply to your case.
The Standard ASP.net application Cache could work for you here. Check out this article. With this you get built in management of dependance (the file changes) or time based expiry. The linked article shows an On_start application
My concern is the size of what you want to cache.
Cheers guys
I also found this article which addresses the options: http://www.asp.net/data-access/tutorials/caching-data-at-application-startup-cs
Nothing really gives recommendations for large amounts of data - or what is even defined as 'large amounts'. I'll keep doing my research, but Redis looks pretty good
Related
Here's my issue, we have a large patient object that is used on multiple screens throughout the admin. Each screen contains different information about the same patient. It can't all be on one screen.
The only time I want to persist the patient is when the user clicks save. I need to have an in memory patient somewhere. A user may be in the admin, change patient information on various screens, run validation and decide to not save that patient. This is typical use.
Is it ok to store this patient in the session? Or, is there a better approach to do this? At most this admin would have 20 users with access.
Opinions may vary on this. Session is tricky, especially if you use something other than in-memory session. Distributed session will break a non-serializable object. If this object is a simple POCO or object you control, try your best to make it play with serialization. If it does you're set. For an admin tool without much load I'd say you'd be fine.
Hey I found this - know nothing about the site, but illustrates my point:
https://www.fortify.com/vulncat/en/vulncat/dotnet/asp_dotnet_bad_practices_non_serializable_object_stored_in_session.html
I had a similar situation with similar amount of users. I did it and it worked great.
My situation was about scheduling events.
Someone would create an event and through multiple web pages would modify and configure this event. When they were all done it would save all the details to SQL. In the end, I was surprised just how well it worked.
Session should be fine here. You have what appears to be a light user load... but you might want to check exactly how much memory the object takes up, multiply that by the maximum number of users, and see where you are.
If you want to avoid the session altogether, you could use System.Web.Caching to store the object instead, and key the stored object using the users identifier plus some constant string.
In either case, you'll want to be aware of how many web servers are running the application. If it's just one web server, no worries. If you have multiple web servers, you'll want to make sure they are "sticky" - then the user is guaranteed to have all requests processed by the same server. How this is done is entirely dependent on your flavor of load balancing... normally the "IT folks" handle this for you.
I'm creating an ASP.NET MVC app that uses EF to perform all DB tasks.
There's a couple of related tables in the database that never change and I was thinking on creating a static collection that retrieves the data from those two tables (it's a few hundred records) the first time it is requested and just stores it in an object to prevent hitting the database every time.
Since I've read several people saying that you should avoid static objects in ASP.NET I was wondering if this was a bad practice or if it is acceptable for scenarios like this (read-only and small amount of data which should prevent concurrency problems).
Also I would like to know if there are other better alternatives to do this.
Thanks.
I have done exactly what you are planning on doing for exactly the same reason. It has been working well for several years already.
Just make sure that you get the initialization of the data right and you should be fine. When initializing, keep in mind:
Don't use locking if at all possible (or your app will deadlock 2
minutes before you're going on vacation)
You MUST NOT under any circumstance let a static constructor fail
Make sure no consumer of your cache has the ability to modify it
If the data isn't really static and you would actually need to re-read it fairly often then this might not be the best solution.
Just in case you're wondering, I've used this approach to cache for instance country data, currency data (base data, not rates), sales unit data (pcs, m, kg etc). These are all stored in a database but almost never change.
It is not a very good approach to use static objects. I would use something like RavenDB which can be used to store your settings or DB data in-memory. It has a very small footprint and is very fast. It has full LINQ support.
So there seems not be any pretty answer to the question of how pass data between multiple pages. After having done a little homework here's why (or at least what I've gleaned):
ViewState variables don't persist across pages.
Session variables are volatile and must be used sparingly.
Cookies have potential safety issues and take time and must be kept small.
Storing vars in the URL has limits to the amount of data and can be unsafe.
Storing vars temporarily in a db is a real pita because you add one table per object that might be potentially passed to another page.
So far it is looking like I will be using hidden fields to pass a keyid and unique id to the next page and then retrieve the data from the db. What are your thoughts on all of this? What is the best way to go about doing any of it? I am early in the development of this app, so making changes now is preferred.
edit: I am anticipating a lot of users using this application at any one time, does that affect whether or not I should be using SQL Server based Session?
If you want to persist state, yes store it in the database since you don't have to worry about an expiration. The Session is similar except you have to worry about the Session expiring. In both cases concurrent calls that write similar data to the same area could cause problems and need to be accounted for.
Session is good when you don't have to worry about multiple web servers or timeout issues. The database gives you more scalability but at a cost of doing lots of db read/writes and you have to consider clean up.
Personally I would try to use the following decision tree:
Is the data simple, short and not private -> query string
Is the data less simple but only needs to exist for a short time -> session
Will the data be needed across multiple area and be persistent for long period of time -> database
Of course there is more to it that this but that should give you a basic outline of considerations since you are just starting out. Keep it simple. Don't try to over engineer a solution if a simple query string will suffice. You can always over engineer late as long as you have kept it simple to start.
I think context is important here, e.g. what are you trying to pass between pages and why?
If you are dealing with complex, multi-part forms, then you can implement the form in a single page, simply showing or hiding relevant element. Use usercontrols and custom controls as much as possible to facilitate isolation and reusability. This makes life a lot easier across the board.
Anything that is user-generated is almost certainly going to end up in a database anyway - so #5 does not seem relevant. That is you shouldn't have to store data "temporarily" in a database- what data would need to be persisted between pages that isn't part of your application.
Anything else would seem to be session related and not that much data.
I could add some more thoughts if I knew what specifically you were dealing with.
Oh - "cookies have potential safety issues and take time" - you're going to use cookies, unless you don't want to be able to identify return visitors. Any potential safety issues would only be a result of bad implementation, and certainly passing data in hidden fields is no better. And you really don't want to get into writing an ASP.NET app that is designed around pages posting to forms other than itself. That's just a headache for many reasons and I can't think of a benefit of doing this as part of basic application design.
Session variables should work fine for your needs.
I would go with StateServer or SQLServer Session state mode. Using mode InProc is the fastest, but it has some issues (including all user sessions getting dropped when a new binary is pushed, web.config changes, etc). Sessions are volatile, but you can control the volatility in several ways. Sessions require cookies unless they are configured as cookieless (which I highly recommend you stay away from), but I think that is a reasonable requirement.
Also, you can create a struct or serializable class from which you create objects that you can store in a session variable. The struct or class will allow you to keep all of your data in one place - you only have one session variable to worry about.
There is going to be advantages and disadvantages for any method, it's all about finding the best method. I hope this helps.
All methods have their pros and cons. It would all depend on the scenario you are working in.
Session variables work quite well if used within reason. InProc sessions in traffic heavy sites can quickly drain your resources but you can always switch to SQL Server based session that does most of the DB work for you.
I'm doing a survey builder, and I think to store the survey in session with a unique guid key until the user creates it fully and saves it I'm thinking it is going to be an array of 100~200 objects (8 properties class)
That sounds like a fair use of Session.
Whether your data is too large depends on quite a few things, such as your web server's memory. The best thing to do is test the performance using Session. If you find your data is too heavy for Session have a look at ASP.NET Profile.
That doesn't sound like that much data unless we are talking about reams of text for each answer. I would not worry about it unless I was working on a web site expected to have thousands of these open at any given point in time.
IMHO I think the data should be stored in something other than the Session.
Session objects can disappear for a myriad of reasons. Would your users be annoyed if their answers are not persisted and needs to start afresh.
Remember to write the data to a persistent store (DB, files, etc) as soon as possible unless the users don't mind starting over.
I agree with ggonsalv. I would store the data somewhere just in case the session is lost. I have been to sites where I fill stuff out and then it looses it near the end. It's not fun to start over.
Let me start by explaining my scenario:
I am developing a quiz engine in C# Asp.net. There is an option to display one question at a time. Since there will be a lot of users accessing the quiz, I do not want to make database calls for each question. Ideally I want to load all the questions on page load, and somehow display one question at a time.
Operations to be done for each question:
The question controls will be generated dynamically depending on question type.
After each question I need to save the user response.
What is the ideal way to do this by conserving database calls? I would really like some directions. Thanks in advance.
Unless you are expecting transaction rates in the high hundreds per second I would not bother.
Premature optimisation will cause real problems and only solve imaginary ones.
Modern DBMSes have very efficient caching mechanisims of thier own, so why re-invent the wheel? Keep your app simple and to the point, lets the DBMS handle caching and solve any performance problems when you actually have them.
I the set of questions is same for all users then you may consider using application wide caching of questions and responses. For this you may get all the questions in one go or fetch questions first time and then cache it.
For per user stuff like saving responses to questions, you can use session object. As you have the questions and their related options in application-wide cache, you can only save question key and selected option in session object.
Ideally I want to load all the
questions on page load, and somehow
display one question at a time.
That implies caching of some kind. Don't use session state, because you can't share it from one user to another.
You probably want to use the Cache object. For example, something like (from your code behind):
DataSet quiz;
string quizName = "quiz#1";
lock (quizLock)
{
quiz = (DataSet)this.Cache[quizName];
if (quiz == null)
{
quiz = DAL.ReadQuiz(quizName);
this.Cache.Insert(quizName, quiz);
}
}
should be relatively easy to achieve using JavaScript.
You simply grab all question store them in a local hashtable (simple javascript object) and display then however you like.
There is a jQuery Quiz plug in which you might use/reuse or just look and learn some tips and tricks (see this page as well)
You could store the questions for a user in a session variable, but you should consider how that affects memory usage. By storing a lot of data for each user, the memory available will limit the number of users that your application can handle.
By getting each question from the database, each page request will take slightly longer to handle, but you will shift the bottle neck from how many users you can handle to how many pages per second you can handle. This is also a softer limit, i.e. the server will just take longer to respond when you are at capacity, instead of starting to throw away user sessions because the memory is running out.