04 September 2006

ADO.NET Entity Framework ContextObject and ASP.NET application

Last month Microsoft published first CTP of ADO.NET Entity Framework. For more info - look here. Although Microsoft is still planning integration between Entity Framework and ASP.NET, I want to show you how to handle ADO.NET Entity Framewrok context object in ASP.NET application. This post is inspired from NHibernate session management.
The idea is simple: Context object will be stored in ASP.NET session and after the request HTTPModule will free it. I'm using ASP.NET session instead of ASP.NET context to further extend this example to support session per application transaction strategy. If you are wondering what is "session per application transaction" take a look at NHibernate session management. Here is the code of the implementation:

public class ContextManager<T>where T: ObjectContext, new()
{
    public static T ObjectContext
    {
        get
        {
            T resultContext;
 
            if (HttpContext.Current.Items.Contains(
                ContextConst.CONTEXT_OBJECT_SESSION_KEY))
            {
                resultContext =
                    (T)HttpContext.Current.Items[
                        ContextConst.CONTEXT_OBJECT_SESSION_KEY];
            }
            else
            {
                resultContext = new T();
                HttpContext.Current.Items[ContextConst.CONTEXT_OBJECT_SESSION_KEY] = 
                    resultContext;
            }
 
            return resultContext;
        }
    }
 
    public static bool isActiveObjectContext
    {
        get
        { 
            return HttpContext.Current.Items.Contains(
                ContextConst.CONTEXT_OBJECT_SESSION_KEY);
        }
    }
 }

public class ContextHttpModule : IHttpModule 
{
    #region IHttpModule Members
 
    public void Init(HttpApplication context)
    {
        context.EndRequest += new EventHandler(OnEndRequest);
    }
 
    public void Dispose()
    {
        //Intentionaly not implemented
    }
 
    public void OnEndRequest(Object sender, EventArgs e)
    {
        if (HttpContext.Current.Items.Contains(ContextConst.CONTEXT_OBJECT_SESSION_KEY))
        {
            ObjectContext contextObject = 
                (ObjectContext)HttpContext.Current.Items[
                    ContextConst.CONTEXT_OBJECT_SESSION_KEY];
 
            contextObject.Dispose();
        }
    }
 
    #endregion
}


internal class ContextConst
{
    public const string CONTEXT_OBJECT_SESSION_KEY =
        "ContextConst.CONTEXT_OBJECT_SESSION_KEY";
}

Now, lets look how the code above can be used. First lets make some corrections to web.config file:

<connectionStrings>
  <add name="Duwamish7Model.Duwamish7" 
       connectionString="metadata=C:\Temp\ContextObject\Model;
          mapping=C:\Temp\ContextObject\Model;
          provider=System.Data.SqlClient;
          provider connection string=&quot;Data Source=ns-server;
          Initial Catalog=Duwamish7;Integrated Security=True&quot;"
    providerName="System.Data.Mapping" />
</connectionStrings>


<httpModules>
  <add name="ContextObjectManager"
       type="ObjectContextManager.ContextHttpModule, ObjectContextManager"/>
</httpModules>
Having all of the above done, we can write somethig like this:

Duwamish7 db = ContextManager<Duwamish7>.ObjectContext;
 
Query<Authors> query = db.GetQuery<Authors>(
    "SELECT VALUE a FROM Authors AS a WHERE a.PKId > 144");
 
Repeater1.DataSource = query;
Repeater1.DataBind();


P.S. The code above is not tested for concurrency problems.

No comments: