I'm writing an ASP.NET MVC5 Application, I know that the actions where session["foo"] = bar are ran sequentially, now to avoid this, i want to store some informations into a MemoryCache object and not in session, but my doubt is: Is the cache managed like the session? So the actions where i put ObjectCache.Set("foo", bar, null) are ran sequentially like for session?
I know the scope difference between cache and session but for me and in this case it's not important.
Thank to everyone
I understand that you try to avoid the session lock on the page.
The cache is not lock the full page access so the answer is that the cache is not run sequentially.
There are two kind of cache, one in memory that use static dictionary to keep the data and one that save the cache on database, that use files to save the data. Both of them locks the data only for the period of read/write, while the session is lock the full access on the page from start to the end of it.
So use cache, but close the session on the page you have this issue. Also have in mind that if you use web garden then the cache on memory can have multiple different data because memory cache have its own static space on each pool.
Also the session is different for each user, the cache is the same for all users.
some more to read : ASP.NET Server does not process pages asynchronously
I think the term you are looking for is thread safety - especially around concurrent access, typically writing.
Seems that according to MSDN, System.Runtime.Caching.MemoryCache is indeed thread safe. See also: Is MemoryCache.Set() thread-safe?
Related
I am designing an online time tracking software to be used internally. I am fairly new to c# and .NET though I have extensive PHP experience.
I am using Windows Forms Authentication, and once the user logs in using that, I create a Timesheet object (my own custom class).
As part of this class, I have a constructor that checks the SQL DB for information (recent entries by this user, user preferences, etc.)
Should I be storing this information in a session? And then checking the session object in the constructor first? That seems the obvious approach, but most examples I've looked at don't make much use of sessions. Is there something I don't know that others do (specifically related to .NET sessions of course)?
EDIT:
I forgot to mention two things. 1. My SQL DB is on another server (though I believe they are both on the same network, so not much of an issue)2. There are certain constants that the user will not be able to change (only the admin can modify them) such as project tasks. These are used on every page, but loaded the first time from the DB. Should I be storing these in a session? If not, where else? The only other way I can think of is a local flat file that updates each time the table of projects is updated, but that seems like a hack solution. Am I trying too hard to minimize calls to the DB?
There is a good overview on ASP.NET Session here: ASP.NET Session State.
If you don't have thousands of clients, but need "some state" stored server-side, this is very easy to use and works well. It can also be stored in the database in multi server scenarios, without changing a line in your code, just by configuration.
My advise would be not to store "big", or full object hierarchies in there, as storing in a session (if the session is shared among servers in a web farm in a database for example) can be somewhat costy. If you plan to have only one server, this is not really a problem, but you have to know that you won't be able to easily move to a multiple server mode easily.
The worst thing to do is follow the guys who just say "session is bad, whooooo!", don't use it, and eventually rewrite your own system. If you need it, use it :-)
I would shy away from session objects. And actually I would say look into .net MVC as well.
The reason I don't use the session is because I feel it can be a crutch for some developers.
I would save all of the information that you would have put into a session into a db. This will allow for better metrics tracking, support for Azure (off topic but worth mentioning) and is cleaner imo.
ASP developers know session state as a great feature, but one that is somewhat limited. These limitations include:
ASP session state exists in the process that hosts ASP; thus the actions that affect the process also affect session state. When the process is recycled or fails, session state is lost.
Server farm limitations. As users move from server to server in a Web server farm, their session state does not follow them. ASP session state is machine specific. Each ASP server provides its own session state, and unless the user returns to the same server, the session state is inaccessible. http://msdn.microsoft.com/en-us/library/ms972429.aspx
One of the main problems with Session is, that by default, it is stored in memory. If you have many concurrent users that store data in the session this could easily lead to performance problems.
Another thing is that application recycle will empty your in memory session which could lead to errors.
Off course you can move your session to SqlServer or a StateServer but then you will lose on performance.
Look into the HttpContext.User (IPrincipal) property. this is where user information is stored in the request.
Most people avoid session state simply because people like to avoid state in general. If you can find an algorithm or process which works all the time regardless of the previous state of an object, that process tends to be more fool proof against future maintenance and more easily testable.
I would say for this particular case, store your values in the database and read them from there any time you need that information. Once you have that working, take a look at the performance of the site. If it's performing fine then leave it alone (as this is the simplest case to program). If performance is an issue, look at using the IIS Cache (instead of session) or implementing a system like CQRS.
Session State Disadvantage
Session-state variables stay in memory until they are either removed or replaced, and therefore can degrade server performance. Session-state variables that contain blocks of information, such as large datasets, can adversely affect Web-server performance as server load increases. Think what will happen if you significant amount of users simultaneously online.
NOTE :- I haven't mentioned the advantages because they are straightforward which are : Simple implementation, Session-specific events, Data persistence, Cookieless support etc.
The core problem with sessions are scaleability. If you have a small application, with a small number of users, that will only ever be on one server, then it may be a good route for you to save small amounts of data - maybe just the user id - to allow quick access to the preferences etc.
If you MAY want multiple web servers, or the application MAY grow, then don't use session. And only use it for small pieces of information.
I'm thinking over an ASP.NET application that uses ESENT for persistance.
At this point this is just my hobby project, so the requirements are very flexible. However I'd like it to work on Windows 7, Windows 2008, and 2008 R2, with .NET 3.5 and higher, and default IIS settings.
In ESENT, most operations require you to open a session object. The documentation says: "A session tracks which thread it was used on, and it will throw an error if used on multiple threads with an open transaction." The API documentation mentions the native threads, not managed threads.
I assume the open session operation is relatively expensive, that's why I don't want to open/close session for every HTTP request.
Here're my questions, finally.
How in asp.net do I initialize / deinitialize something exactly once, on every native thread that executes my C# code?
Will the code like posted below work for me?
Is there something bad I don't know in keeping the asp.net managed thread constantly pinned to the native thread with BeginThreadAffinity method? Wont my sessions leak after the IIS is under the load for a month without a single reboot?
Thanks in advance!
class MySession: IDisposable
{
[ThreadStatic]
private static MySession s_session = null;
public static MySession instance
{
get
{
return s_session ?? ( s_session = new MySession() );
}
}
private MySession()
{
Thread.BeginThreadAffinity();
// Open a new session, store the handle in non-static data member.
}
void IDisposable.Dispose()
{
// Close the session.
Thread.EndThreadAffinity();
}
}
One good approach is to create a pool of sessions and have threads grab a session from the pool and then return the session when done. A session can be used by different threads, but ESENT will complain if you migrate a session between threads while a transaction is active (it is possible to disable that behaviour though).
Several large server apps that use ESENT have taken the session pool approach and it works well for them.
our current research shows that instancing a new session in page_load and disposing it in page_unload easily yields 600 reqs/sec with wcat for a simple script that seeks on an index, and does two other seeks for each returned row.
in other words with proper tuning of esent params a session pool might not be needed.
example above is with maxsessions set to 256. adjusting minimum cache size also helps performance. on a quad core test server with 8 gb ram.
This will probably not work in this form if you really intend to leave the session open across requests.
The finalizer will run on a separate thread and closing the session will throw an error.
Most probably
JET_errSessionInUse -
session was in use on another thread, or the session was not set or reset properly in JetEndSession() during Dispose().
If you really must use ESENT, maybe you can fire up and manage a dedicated pool of threads by hand and marshal calls to/from them.
Coming from an Classic ASP background I'm pretty cautious about placing objects into Session.
Would it be a bad idea for me to store an object of type Dictionary into Session within .NET?
Well, you won't have some of the issues that you would have with ASP. .net is not STA COM, so the thread affinity problems that you had with ASP are not going to hurt you (unless you try to store an STA COM object in the session, or in your dictionary).
Do be careful about concurrent access, though. If it is possible that multiple threads could access the dictionary (do to asynchronous page code, or maybe AJAX calls), then you will need to apply appropriate locking to the dictionary.
Well, it depends on what you want to achieve, for simple things like persisting state between page postbacks, I recommend you to use the ViewState.
You can put anything into Session... You just have to make sure not too much data is put into Session as this takes up server resources. This is something that will not be visible when testing your site at first, only when you deploy it and a lot of users start using it, as every user has its own Session object on the server.
The big picture issues aren't really different than classic ASP (though I confess I didn't think about the differences that JMarsch raised). The answer depends on numerous factors:
How many concurrent sessions you expect (and how many you intend to support)
The size of the Dictionary
Your server(s)'s memory characteristics
Everything else your server(s) need to do
i have a client server application, the server uses nhibernate.
i wanna know how should i use the session?
per call?
per client?
single?
other way?
and how can i keep the session cache in the server ?
and also i wanna know if the session is thread safe?
You should use one session per unit of work. If that includes multiple operations, so be it.
Use the session.BeginTransaction() to wrap the unit of work and commit once all the items are done.
Sessions are NOT thread safe, but the session factory is (which you definitely want to keep around).
NHiberate has various cache options for data, but the sessions are meant to be used and disposed.
Normally it's done one per request. You can create HttpApplication, which opens the session at the beginning of request and closes at the end of request (example).
Per call should be the usual solution
There really is no one right answer to the question of session lifetime. You can make any session lifetime work, it depends on your requirements. Sessions are not thread safe, but session factories are.
To keep the cache around, you need to keep the session around. It is likely to be fairly challenging to keep the cache around and keep the cache correct in anything but simple single user, single process applications.
There's a great example I've used from NHibernate Best Practices.
The code example uses a session per ASP.NET request.
At the moment I am working on a project admin application in C# 3.5 on ASP.net. In order to reduce hits to the database, I'm caching a lot of information using static variables. For example, a list of users is kept in memory in a static class. The class reads in all the information from the database on startup, and will update the database whenever changes are made, but it never needs to read from the datebase.
The class pings other webservers (if they exist) with updated information at the same time as a write to the database. The pinging mechanism is a Windows service to which the cache object registers using a random available port. It is used for other things as well.
The amount of data isn't all that great. At the moment I'm using it just to cache the users (password hashes, permissions, name, email etc.) It just saves a pile of calls being made to the database.
I was wondering if there are any pitfalls to this method and/or if there are better ways to cache the data?
A pitfall: A static field is scoped per app domain, and increased load will make the server generate more app domains in the pool. This is not necessarily a problem if you only read from the statics, but you will get duplicate data in memory, and you will get a hit every time an app domain is created or recycled.
Better to use the Cache object - it's intended for things like this.
Edit: Turns out I was wrong about AppDomains (as pointed out in comments) - more instances of the Application will be generated under load, but they will all run in the same AppDomain. (But you should still use the Cache object!)
As long as you can expect that the cache will never grow to a size greater than the amount of available memory, it's fine. Also, be sure that there will only be one instance of this application per database, or the caches in the different instances of the app could "fall out of sync."
Where I work, we have a homegrown O/RM, and we do something similar to what you're doing with certain tables which are not expected to grow or change much. So, what you're doing is not unprecedented, and in fact in our system, is tried and true.
Another Pitfall you must consider is thread safety. All of your application requests are running in the same AppDomain but may come on different threads. Accessing a static variable must account for it being accessed from multiple threads. Probably a bit more overhead than you are looking for. Cache object is better for this purpose.
Hmmm... The "classic" method would be the application cache, but provided you never update the static variables, or understand the locking issues if you do, and you understand that they can disappear at anytime with an appdomain restart then I don't really see the harm in using a static.
I suggest you look into ways of having a distributed cache for your app. You can take a look at NCache or indeXus.Net
The reason I suggested that is because you rolled your own ad-hoc way of updating information that you're caching. Static variables/references are fine but they don't update/refresh (so you'll have to handle aging on your own) and you seem to have a distributed setup.