2010-03-20 5 views
6

Necesito que mi linq al sql datacontext esté disponible en toda mi capa empresarial/de datos para que todos mis objetos de repositorio puedan acceder. Sin embargo, dado que esta es una aplicación web, quiero crearla y destruirla por solicitud. Me pregunto si funcionaría una clase singleton que pueda crear y conectar perezosamente el contexto de datos al HttpContext actual. Mi pregunta es: ¿se eliminaría automáticamente el contexto de datos cuando termine la solicitud? A continuación está el código de lo que estoy pensando. ¿Esto lograría mi propósito: tener una instancia de contexto de datos segura para subprocesos que está disponible de forma perezosa y se elimina automáticamente cuando finaliza la solicitud?adjuntando linq al sql datacontext a httpcontext en la capa empresarial

public class SingletonDC 
{ 
    public static NorthwindDataContext Default 
    { 
     get 
     { 
      NorthwindDataContext defaultInstance = (NorthwindDataContext)System.Web.HttpContext.Current.Items["datacontext"]; 
      if (defaultInstance == null) 
      { 
       defaultInstance = new NorthwindDataContext(); 
       System.Web.HttpContext.Current.Items.Add("datacontext", defaultInstance); 
      } 
      return defaultInstance; 
     } 
    } 
} 

Respuesta

8

Lo que tiene sentido imaginar - utilizando el contexto de la petición HTTP para guardar cosas - pero No, objetos desechables almacenados en la HttpContext actual serán no auto-mágicamente ser eliminados cuando la solicitud termina. Tendrás que manejarte a ti mismo, de alguna manera.

Hay un evento de "Solicitud de finalización" en el que puede enganchar fácilmente, por ejemplo, utilizando el código que coloca en Global.asax.cs. En su método Application_EndRequest(), puede llamar al Dispose() manualmente en cada objeto en la lista que lo requiera.

Una forma de hacerlo es recorrer cada elemento en el contexto, probar IDisposable y luego llamar a Dispose si corresponde.

protected void Application_EndRequest(Object sender, EventArgs e) 
{ 
    foreach (var key in HttpContext.Current.Items.Keys) 
    { 
     var disposable = HttpContext.Current.Items[key] as IDisposable; 
     if (disposable != null) 
     { 
      disposable.Dispose(); 
      HttpContext.Current.Items[key] = null; 
     } 
    } 
} 

creo que oughtta lo hacen. ASPNET no hace esto por usted automáticamente. Por supuesto, necesita protección contra excepciones y demás, antes de usar este código en una aplicación real.


Keith Craig de Vértigo escribió a relevant post on the topic a while ago, describiendo lo que quiere hacer como un patrón, en otras palabras, una forma de hacer las cosas que deberían ser repetido. Él proporciona una clase para ayudar con eso, para cargar el contexto DB y colocarlo en el contexto actual. El enfoque tiene algunos inconvenientes: puede leer sobre ellos en la discusión de comentarios en esa publicación. También hay un grupo de artículos relacionados citados en los comentarios.

3

El código de Cheeso generará un InvalidOperationException"Collection was modified; enumeration operation may not execute" porque está intentando modificar los elementos de HttpContext sobre los que se está iterando.

Puede usar una copia de la lista para evitar esto.

protected void Application_EndRequest(Object sender, EventArgs e) 
{ 
    var keys = new ArrayList(HttpContext.Current.Items.Keys); 

    foreach (var key in keys) 
    { 
     var disposable = HttpContext.Current.Items[key] as IDisposable; 
     if (disposable != null) 
     { 
      disposable.Dispose(); 
      HttpContext.Current.Items[key] = null; 
     } 
    } 
} 
Cuestiones relacionadas