lunes, diciembre 21, 2009

Compartir DataContext por cada HTTP Request

Trabajando en proyectos donde, por petición especifica del cliente, debo usar LinqToSql para mi acceso a datos. Donde además se me ha pedido usar las entidades generadas por LinqToSql  como mis entidades de negocio. Al abstraer mi acceso a datos con repositorios, Esto con la finalidad de poder hacer pruebas unitarias en mi capa de servicios, me encontré con la necesidad de compartir el DataContext a través de mis repositorios, en si lo que necesitaba era tener un solo DataContext por cada petición HTTP.
Para ello mis repositorios reciben en el constructor un IDataContextFactory la cual será la encargada de pasarle el datacontext a los repositorios
public interface IDataContextFactory<T> where T: DataContext, new()
{                                                                  
    T GetCurrentDataContext();                                     
    void DisposeCurrentDataContext();                              
}                                                                  

Así mis repositorios no necesitan saber de donde viene el datacontext. Aquí esta la implementación de esta interfaz para tener un datacontext por request

public class WebDataContextFactory<T>: IDataContextFactory<T> where T : DataContext, new()
{                                                                                         
    public T GetCurrentDataContext()                                                      
    {                                                                                     
        var dataContext = HttpContext.Current.Items[typeof(T)] as T;                      
        if (dataContext == null)                                                          
        {                                                                                 
            dataContext = new T();                                                        
            HttpContext.Current.Items[typeof(T)] = dataContext;                           
        }                                                                                 
                                                                                          
        return dataContext;                                                               
    }                                                                                     
                                                                                          
    public void DisposeCurrentDataContext()                                               
    {                                                                                     
        var dataContext = HttpContext.Current.Items[typeof(T)] as T;                      
        if (dataContext != null)                                                          
            dataContext.Dispose();                                                        
    }                                                                                     
}                                                                                         

lo que hago es guardar el datacontext dentro del diccionario Items del actual HttpContext, el cual esta vivo solo para ese request y se puede utilizar el evento request end del HttpAplication para hacer dispose del datacontext a través del IDataContextFactory

2 comentarios:

  1. lo unico que me preocupa es el Dispose, que debe ser llamado por cada DataContext que instancies (<= eso es una palabra?), como remedio se podria agregar un metodo que tomara un parametro HttpApplication como parametro y se subscribiera al evento EndRequest para hacer el Dispose ahi... tampoco me gusta mucho, pero es una opcion

    ResponderEliminar
  2. el dispose lo hago en el método Application_EndRequest del Global.asax.cs llamando al metodo DisposeCurrentDataContext del IDataContextFactory

    ResponderEliminar