Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework: Singletonish ObjectContext - Good, Bad, or Overthinking?

The idea is to create a class that exposes a context but handles the storage of it in a web application.

Currently this is what I have:

public class EntityContext
{

    private static String MAIN_CONTEXT_KEY = "MainContext";
    private static TISQLEntities _context;

    public static void RemoveContext()
    {
        if (
            HttpContext.Current != null 
            && 
            HttpContext.Current.Items[MAIN_CONTEXT_KEY] != null
           )
        {
            ((TISQLEntities)HttpContext.Current.Items[MAIN_CONTEXT_KEY]).Dispose();
            HttpContext.Current.Items[MAIN_CONTEXT_KEY] = null;
        }

        if (_context != null)
        {
            _context.Dispose();
            _context = null;
        }
    }

    public static TISQLEntities Context
    {
        get
        {
            if (HttpContext.Current == null)
            {
                if (_context == null)
                {
                    _context = new TISQLEntities();
                }

                return _context;
            }

            if (HttpContext.Current.Items[MAIN_CONTEXT_KEY] == null)
            {
                HttpContext.Current.Items[MAIN_CONTEXT_KEY] = new TISQLEntities();
            }

            return (TISQLEntities)HttpContext.Current.Items[MAIN_CONTEXT_KEY];
        }
    }
}

And then in the Global.asax file:

protected void Application_EndRequest(object sender, EventArgs e)
{
    EntityContext.RemoveContext();
}

The idea is that if this is being run with a web application, the context is created on first need (and saved to the current HttpContext) and torn down whenever the request is over.

If this is a UnitTest situation it is against created on first need and removed in the TestCleanup (Not as important in this post but just wanted to clarify the _context object).

Now the idea behind this is in the least to not have to do this:

using(TISQLEntities context = new TISQLEntities())
{
  ....
}

Everytime I want to query. I realize this may be me being lazy, but I just think that it's easier and cleaner to have:

EntityContext.Context.User.Select(...)

And avoids "using" which I try to avoid for most cases. On top of that, I'm not creating 9001 contexts per postback.

Now what I am curious about is that am I over thinking this? Should I just keep creating a context for every method that needs one? Say on a post back I have to:

  • Get the user from an ID
  • Get a site from an id
  • Add the Site to the User (user.Site = foundSite)
  • Save the user

That could entail at least 3 contexts. Is entity framework smart enough that it's ok to just keep creating contexts whenever?

like image 443
Programmin Tool Avatar asked Feb 12 '09 18:02

Programmin Tool


3 Answers

You are implementing the equivalent of NHibernate's session per request pattern which is a good construct in NHibernate. While I can't say 100% for sure that it's applicable to EF it most likely is. Further expanding on other session management patterns is the Session per Business Conversation which allows NHibernate to extend holding a session over the duration of a HttpSession by disconnecting and reconnecting the session as opposed to destroying and creating. If the EF allows a similar ability as opposed to keeping a static open connection you could look at how I implemented that pattern using AOP on my blog through my profile.

like image 54
Chris Marisic Avatar answered Nov 04 '22 01:11

Chris Marisic


Check out this blog entry that provides some more details about creating a singleton for the Entity Framework context and why this wouldn't work in ASP.NET and comes up with a solution that does something similar as you suggest.

like image 37
Jeroen Huinink Avatar answered Nov 04 '22 00:11

Jeroen Huinink


If you are trying to implement something like NHibernate does with its Session, I think its a good idea to have this kind of pattern. I know for sure that in LinqToSql the context object implementation is more like an entrypoint class thats acts as a facade. I would like to think LinqToEntities is similar. You could have a factory implementation to get a datacontext to your model where you can recycle the datacontext. If you go the singleton way consider bottleneck ,availability and responsibility of the singleton object.

like image 43
Perpetualcoder Avatar answered Nov 04 '22 01:11

Perpetualcoder