Telerik blogs

The stateless nature of the Http protocol brings quite a deal of concerns about the handling of the IObjectScope in a web application. Few questions usually arise when dealing with entity containers (like the DataContext in Linq to SQL or the IObjectScope in Telerik OpenAccess ORM): where to initialize the scope, where to dispose it, how to integrate with the Page’s lifecycle, etc.. In this post we share our views on the best-practices approaches that secure safe and consistent use of the IObjectScope in web scenarios.

The desired result of the used patterns is to have one object scope, initialized on every postback and shared between various pages, or user controls that are part of a web application. 

The first approach (and maybe the easiest way of accomplishing that goal) is using a Master Page. It’s is very easy to have the object scope as a member of the Master Page and then access it from any page that has the appropriate master page set. That way the scope initialization is done in only one place and the code is efficiently used e.g. we save repeats of the same code in various places.

public partial class ScopeHolder : System.Web.UI.MasterPage
{        
 
private IObjectScope scope;

       
public IObjectScope Scope
       
{
           
get
           
{
               
if (scope == null)
               
{
                   
scope = ObjectScopeProvider1.GetNewObjectScope();
               
}
               
return scope;
           
}
           
set { scope = value; }
       
}

 

The disposal of the scope is maybe as important operation and we are executing it in the same generic manner – in the Page_Unload event handler of the master page.

  public void Page_Unload(object sender, EventArgs e)
 
{
      
scope.Dispose();
      
base.Dispose();
 
}

 

Accessing the object scope now is really easy. Loading it in Page_Init on any page that requires it is a common way of working with it.

public partial class _Default : System.Web.UI.Page 
{ 
   
private ScopeHolder myScopeHolder; 
   
private IObjectScope cachedScope; 
         
   
protected void Page_Init(object sender, EventArgs e) 
   
{ 
       
myScopeHolder = (ScopeHolder)Master; 
       
cachedScope = myScopeHolder.Scope; 
   
}

This approach of handling the object scope has its faults as well. The most obvious one – projects that do not use Master Pages, or more concerning, projects that can’t use such pattern like most CMS web applications could not benefit from this approach.

The solution that was proven as very successful so far is using the HttpContext.Items collection to store the object scope and access it from any independent component on the page. We implemented a sample ScopeFactory helper class that provides the necessary logic for the operation:

    public class ScopeFactory 
   
{ 
       
public static IObjectScope GetPerRequestScope(HttpContext context) 
       
{ 
           
string key = HttpContext.Current.GetHashCode().ToString("x") + Thread.CurrentContext.ContextID.ToString(); 
           
IObjectScope scope; 
           
if (context == null) 
           
{ 
               
scope = ObjectScopeProvider1.GetNewObjectScope(); 
           
} 
           
else 
           
{ 
               
scope = (IObjectScope)context.Items[key]; 
               
if (scope == null) 
               
{ 
                   
scope = ObjectScopeProvider1.GetNewObjectScope(); 
                   
context.Items[key] = scope; 
               
} 
           
} 
           
return scope; 
       
} 
   
}

 

From here on, every component in the web application obtains the object scope in the same generic manner:

IObjectScope scope = ScopeFactory.GetPerRequestScope(HttpContext.Current);
//Do some data-access..

 

So, to summarize in the end, there are numerous ways of handling the object scope when working with OpenAccess. After all it is a choice that the developer has to make.  These two have proved to cover most of the user cases.

Comments

Comments are disabled in preview mode.