views:

245

answers:

4

I have been reading articles about state management in ASP.NET for few days for my web application. In this application, one user can create/save/execute queries, and I need to keep each parameter of a query before the user can save the query.
These parameters are string values, but the global size for one user may exceed few megabytes. We plan to have our website running w/ ~100 users simultaneously.

In these conditions, I believe that it will not be good to store these values in session w/ in-proc mode.

We already implemented a ProfileProvider:SqlProfileProvider, using a caching mechanism and with AutoSave=true.

What is the best solution: storing these values in profile or in session but in an SQL database?

+1  A: 

Depends on your server memory and how concerned you are about it. A database is always nice for this type of thing because you have better concurrency and more stable method for storing your data.

My recommendation is that you use a sliding expiration on the cached data, say 10-20 minutes or so. That way, you won't be consuming so many server resources because as users become inactive their session data will be evicted.

For an example of how to do sliding expiration caching (also referenced here), you can do this:

public static void AddToCache(string key, Object value, int slidingMinutesToExpire)
{
        if (slidingMinutesToExpire == 0)
        {
            HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.NotRemovable, null);
        }
        else
        {
            HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(slidingMinutesToExpire), System.Web.Caching.CacheItemPriority.NotRemovable, null);
        }
    }
dcp
+1  A: 

1) One can keep session as Out Of Proc (on SQL Server), so the question is more about where to keep them: in memory or in database. If you keep in memory, then it will be destroyed eventually automatically. If you keep in database, then you can use this data across sessions. Decide whether you need these parameters to be saved across sessions (user can switch computers; user can open your application once in a while) - does he need these parameters to be kept for him?

2) Think about optimization - few megabytes of parameters per user?!? If that means that user can have hundreds of queries and they should be available next time user logs into the system, then keep all that in the database.

Vitaly
"If you keep in memory, then it will be destroyed eventually automatically" Doesn't it depend on how it's added to the cache? If you look at my code sample above, you'll see that one of the parameters you can pass is "System.Web.Caching.CacheItemPriority.NotRemovable". That would mean it will persist until work process is recycled unless I'm mistaken. So I think it's important to consider when the session/application state is released.
dcp
@Vitaly Actually, when the user is building his query, he will browse different pages to select his parameters. So I need to keep these parameters somewhere. Then the user can choose to save his query, and then the global query will be persisted in DB.
jon
@Dave - yep, you can set it up to happen on process recycle. But still there's a difference between keeping in session and in database. From database it's deleted only if you run "delete" manually.
Vitaly
@jon - got it. Make sure you do need to keep intermediate data on the server and not on the client (you can have JavaScript work for you here). I'm not saying that this is the way to go (because I don't know the exact problem), but you can have javascript keeping all the data and sending the final result in JSON to server.
Vitaly
+1  A: 

We've had some level of success persisting user details to disk to keep it out of memory. When you want something specific you then have to read it back into memory and this can be a bit slow, but it works.

For instance, you can serialize some of the objects and write them to files on the web server's hard drive. Name the files according the session ID, username, whatever, and then you can read/write from/to the files as and when you need it.

Sonny Boy
+1  A: 

The best solution depends on whether you plan to grow beyond a single server. In a load balanced configuration, InProc session state won't work correctly (without using sticky sessions, which presents other problems). Out of proc session state, such as State Server or SQL Server, requires that your state information be serialized and deserialized for each page access. With multiple MB per user, that could be very slow.

Cache is another option, as suggested by Dave. One issue there might be whether the cache needs to be kept in sync from one web server to another.

The usual approach to this kind of problem is to store the data in the DB and in Cache, and to only retrieve it for those pages where it's really needed (unlike Session, which is read for every page). Then use SqlDependency or SqlCacheDependency to cache the data in a way that it can be updated on multiple servers if the DB changes.

RickNZ
Ok I currently using both cache and DB for retrieving some profile properties values.Reading your answer, I understand it is better to use this for storing the queries' parameters, rather than session state out of proc?
jon
I would suggest custom data access code / tables, if possible, rather than either the ASP.NET Profile provider or Session state; it will give you more control, better performance, and easier integration with SqlDependency / SqlCacheDependency.
RickNZ