Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Object Context in ASP.NET Session object?

We have a multi-layered Asp.NET Web Forms application. The data layer has a class called DataAccess which impements IDisposable and has an instance of our Entity Framework Object Context as a private field. The class has a number of public methods returning various collections of Entities and will dispose its Object Context when it is disposed.

Due to a number of problems we've been facing, we decided it would be a big plus to keep the Object Context (or an instance of DataAccess) in scope for longer on the server. A suggestion was made to keep an instance in the HttpContext.Current.Items collection from this post in order to have one instance per Http request.

What I'm wondering is: What issues / concerns / problems would arise from storing an instance of our Object Context in the HttpContext.Current.Session object????

  • I'm assuming that the Session object is finalised and set for garbage collection when a user's session expires, so the instance will be disposed properly.
  • I'm assuming most default browser settings will let our app place its SessionId cookie without qualms.
  • The amount of data the Object Context will be dealing with is not enormous and will not pose a problem for our decent server hardware, with regards to caching over time and relatively few concurrent users.

This will be relatively quick to implement and will not affect our many existing unit tests.

We'll be using AutoFac and a ServiceProvider class to supply instances. When an instance of the ObjectContext is required it will be returned by code similar to this:

private static Entities GetEntities(IContext context)
{
    if (HttpContext.Current == null)
    {
        return new Entities();
    }

    if (HttpContext.Current.Session[entitiesKeyString] == null)
    {
        HttpContext.Current.Session[entitiesKeyString] = new Entities();
    }

    return (Entities)HttpContext.Current.Session[entitiesKeyString];
}

Cheers.

like image 764
andrej351 Avatar asked Mar 05 '10 01:03

andrej351


People also ask

What is the difference between session object and application object?

The Application object is used to store and access variables from any page, just like the Session object. The difference is that ALL users share ONE Application object (with Sessions there is ONE Session object for EACH user).

What is DbContext and DbSet in Entity Framework?

DbContext generally represents a database connection and a set of tables. DbSet is used to represent a table. Your code sample doesn't fit the expected pattern.

What is context in Entity Framework?

The context class in Entity Framework is a class which derives from System. Data. Entity. DbContextDbContext in EF 6 and EF Core both. An instance of the context class represents Unit Of Work and Repository patterns wherein it can combine multiple changes under a single database transaction.

What is DbContext in Entity Framework Core?

A DbContext instance represents a session with the database and can be used to query and save instances of your entities. DbContext is a combination of the Unit Of Work and Repository patterns. Entity Framework Core does not support multiple parallel operations being run on the same DbContext instance.


1 Answers

Storing an ObjectContext in the session state is not something I would consider to be a good practice since the class is intended to encapsulate a unit-of-work pattern - you load up some data (entities), modify them, commit your changes (which are tracked by the UOW), and then you're done with it. UOW objects are not intended or designed to be long-lived.

That said, it can be done without causing any major catastrophes, you just have to make sure you understand what's going on behind the scenes. Please read on if you plan on doing this so that you know what you're getting yourself into and are aware of the trade-offs.


I'm assuming that the Session object is finalised and set for garbage collection when a user's session expires, so the instance will be disposed properly.

This is actually inaccurate, or at least seems to be based on the way it's worded. Session expiry/logout will not immediately cause any of the items to be disposed. They will eventually be finalized/disposed but that is up to the garbage collector and you have no control over when it happens. The biggest potential problem here is if you happen to manually open a connection on the ObjectContext, which won't get closed automatically - if you're not careful, you could end up leaking database connections, something that wouldn't be uncovered with regular unit tests/integration tests/live tests.

The amount of data the Object Context will be dealing with is not enormous and will not pose a problem for our decent server hardware, with regards to caching over time and relatively few concurrent users.

Just keep in mind that the growth is unbounded. If a particular user decides to use your site for 12 straight hours running different queries all day then the context will just keep getting bigger and bigger. An ObjectContext doesn't have its own internal "garbage collection", it doesn't scavenge cached/tracked entities that haven't been used for a long time. If you're sure that this isn't going to be a problem based on your use cases then fine, but the main thing that should be bothering you is the fact that you lack control over the situation.


Another issue is thread-safety. ObjectContext is not thread-safe. Session access is normally serialized, so that one request will block waiting for its session state until another request for the same session is complete. However, if somebody decides to make optimizations later on, specifically the optimization of page-level read-only sessions, requests will no longer hold an exclusive lock and it would be possible for you to end up with various race conditions or re-entrancy problems.

Last but not least is of course the issue of multi-user concurrency. An ObjectContext caches its entities forever and ever until it is disposed. If another user changes the same entities on his own ObjectContext, the owner of the first ObjectContext will never find out about that change. These stale data problems can be infuriatingly difficult to debug, because you can actually watch the query go to the database and come back with fresh data, but the ObjectContext will overwrite it with the old, stale data that's already in the cache. This, in my opinion, is probably the most significant reason to avoid long-lived ObjectContext instances; even when you think you've coded it to grab the most recent data from the database, the ObjectContext will decide that it's smarter than you and hand you back the old entities instead.


If you're aware of all of these issues and have taken steps to mitigate them, fine. But my question would be, why exactly do you think that a session-level ObjectContext is such a great idea? Creating an ObjectContext is really a very cheap operation because the metadata is cached for the entire AppDomain. I'd wager a guess that either you're under the mistaken impression that it's expensive, or you're trying to implementing complicated stateful processes over several different web pages, and the long-term consequences of the latter are far worse than any specific harm you may do by simply putting an ObjectContext into the session.

If you're going to go ahead and do it anyway, just make sure you're doing it for the right reasons, because there aren't a whole lot of good reasons to do this. But, as I said, it's definitely possible to do, and your app is not going to blow up as a result.


Update - for anyone else considering downvoting this because "multiple requests on the same session could cause thread-safety issues", please read the bottom of the ASP.NET Session State Overview documentation. It is not just individual accesses of the session state that are serialized; any request that acquires a session keeps an exclusive lock on the session that is not released until the entire request is complete. Excepting some of the optimizations I listed above, it is impossible in the default configuration for there to ever be two simultaneous requests holding references to the same session-local instance of an ObjectContext.

I still wouldn't store an ObjectContext in the session state for several of the reasons listed above, but it is not a thread-safety issue unless you make it one.

like image 145
Aaronaught Avatar answered Oct 05 '22 11:10

Aaronaught