Following the directions from many articles, I’ve decided to implement the Unit of work pattern to my Linq2SQL DataContexts in my ASP.Net WebForms Application, but I’m not sure if I’m on the right way.
Here’s what I’m accomplishing so far:
1 – On every Request, I catch the Application_AcquireRequestState event (which has access to Session data) in Global.asax and instantiate a new DataContext to bind it to the user’s Session:
void Application_AcquireRequestState(object sender, EventArgs e)
{
// Check if the request is for a Page, Page Method or Handler
if (new Regex(@"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
MyCompany.MyDatabaseDataContext myDatabaseDataContext = new MyCompany.MyDatabaseDataContext();
HttpContext.Current.Session["myDatabaseDataContext"] = myDatabaseDataContext;
}
}
2 – Every Data Access Layer Object (DAO) inherits from a base DAO: GenericDAO:
public class GenericDAO
{
private MyDatabaseDataContext _dbMyDatabase;
protected MyDatabaseDataContext dbMyDatabase
{
get
{
if (_dbMyDatabase == null)
_dbMyDatabase = HttpContext.Current.Session["myDatabaseDataContext"] as MyDatabaseDataContext;
return _dbMyDatabase;
}
}
}
3 – So, in every operation, the DAO use the DataContext Property from its parent class:
public class MyTableDAO : GenericDAO
{
public List<MyTable> getAll()
{
return dbMyDatabase.GetTable<MyTable>().ToList();
}
}
Here’s my concerns…
- First of all, is it ok to store the
DataContextin the user’s Session? What would be another option? My app has a lot of PageMethods calls, so I’m worried the DTX would be invalidated between their async requests if it is stored in the session. - Do I need to capture the
Application_ReleaseRequestStateevent toDispose()of theDataContextand remove it from the session? - If I don’t need to Dispose of it, in every
Application_AcquireRequestState, would it be better toRemove DTX from Session - Create DTX - Store itor justRefreshit? - Also, if I don’t need to Dispose of it, what about
Connections? Would it handle them automatically or I would need to control them too?
I appreciate your time and help 🙂
— EDIT
Here’s the code I’ve reached, following @ivowiblo’s suggestion:
Global.asax
void Application_BeginRequest(object sender, EventArgs e)
{
if (new Regex(@"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
MyCompany.MyDatabaseDataContext myDatabaseDataContext = new MyCompany.MyDatabaseDataContext();
HttpContext.Current.Items["myDatabaseDataContext"] = ceabsDataContext;
}
}
void Application_EndRequest(object sender, EventArgs e)
{
if (new Regex(@"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
if (HttpContext.Current.Items["myDatabaseDataContext"] != null)
{
System.Data.Linq.DataContext myDbDtx = HttpContext.Current.Items["myDatabaseDataContext"] as System.Data.Linq.DataContext;
if (myDbDtx != null)
myDbDtx.Dispose();
}
}
}
GenericDAO
public class GenericDAO
{
protected MyDatabaseDataContext dbMyDatabase
{
get
{
return HttpContext.Current.Items["myDatabaseDataContext"] as MyDatabaseDataContext;
}
}
}
Simple as that!
The best approach is to put it on
HttpContext.Current.Items, creating the DataContext onRequestBeginand dispose it inRequestEnd. In msdn there’s an interesting article about the better management of the DataContext, where it’s suggested to have short-time DataContext instances.This pattern is called
Open session in viewand was created for using NHibernate in web environments.