2010-04-27 13 views
13

estoy aprendiendo ahora EF y tiene una pregunta con respecto a la ObjectContext:Entity Framework ObjectContext reutilización

Debería crear instancia de ObjectContext para cada consulta (función) cuando accedo a la base de datos?

¿O es mejor crearlo una vez (singleton) y reutilizarlo?

Antes de EF que estaba usando la biblioteca de la empresa bloque de acceso a datos y creé instancia de dataacess para la función DataAccess ...

+0

OMI - DI uso para resolver la instancia del objeto de contexto de EF y jugar un poco con los tiempos de vida para comprobar la opción que da los mejores resultados ... – Sunny

Respuesta

14

Definitivamente para cada consulta. Es un objeto liviano, por lo que no se incurre en ningún gasto por crear uno cada vez que lo necesite.

Además, cuanto más tiempo mantenga un ObjectContext activo, más objetos en caché contendrá cuando ejecute consultas en su contra. Esto puede causar problemas de memoria. Por lo tanto, tener el ObjectContext como singleton es una idea especialmente mala. A medida que se utiliza la aplicación, se cargan más y más entidades en el ObjectContext único hasta que finalmente se tenga toda la base de datos en memoria (a menos que se separen las entidades cuando ya no las necesite).

Y luego hay un problema de mantenimiento. Un día intenta rastrear un error pero no puede averiguar dónde se cargó la información que lo causó.

+3

yo estaría de acuerdo con esta respuesta si las únicas opciones eran singleton y en acceso. Pero existe un espectro completo de vidas, algunas de las cuales pueden dar un mejor rendimiento dependiendo de la aplicación. El contexto se almacena en caché por una razón :) Por solicitud es el "más seguro" del grupo al lado del acceso. –

1

No use un singleton .. todos los que usen su aplicación lo compartirán y todo tipo de cosas locas sucederán cuando el contexto del objeto esté rastreando entidades.

yo añadiría como un miembro privado

+0

Me refiero a singleton por sesión (cada usuario lo tiene), y planeo desactivar el seguimiento – verror

+0

Estoy de acuerdo con la primera respuesta de rwwilden. –

15

Creo que la forma más común es utilizarlo por solicitud. Créelo al principio, haga lo que necesite (la mayoría de las veces se trata de operaciones que requieren ObjectContext común), deséchelo al final. La mayoría de los marcos DI respaldan este escenario, pero también puede usar HttpModule para crear contexto y colocarlo en HttpContext.Current.Items. Ese es un simple ejemplo:

public class MyEntitiesHttpModule : IHttpModule 
{ 
    public void Init(HttpApplication application) 
    { 
     application.BeginRequest += ApplicationBeginRequest; 
     application.EndRequest += ApplicationEndRequest; 
    } 

    private void ApplicationEndRequest(object sender, EventArgs e) 
    { 
     if (HttpContext.Current.Items[@"MyEntities"] != null) 
      ((MyEntities)HttpContext.Current.Items[@"MyEntities"]).Dispose(); 
    } 

    private static void ApplicationBeginRequest(Object source, EventArgs e) 
    { 
     var context = new MyEntities(); 
     HttpContext.Current.Items[@"MyEntities"] = context; 
    } 
} 
+1

Creo que esta es una solución menos sostenible que simplemente crear un ObjectContext cuando lo necesite en la capa de datos. Mi objeción a esta solución es que crea una dependencia entre su capa de interfaz de usuario y su capa de datos que no es necesaria. Cómo se comunica con una base de datos es una preocupación interna para la capa de datos. En segundo lugar, puede parecer fácil al principio no tener que preocuparse por problemas de carga diferida, pero algún día intentará localizar un error y no puede determinar dónde salió mal porque no tiene idea de dónde fueron los datos que causaron la falla. Se cargó el error (hablando por experiencia ...) –

+1

@rwwilden: Lo siento, pero ¿cómo crea dependencia entre la interfaz de usuario y la capa de datos? Estoy usando un patrón de repositorio y los repositorios tienen que compartir el contexto. El contexto es inyectado por el contenedor DI. La solicitud no es tan larga y no tiene tantas operaciones que pueden causar tantos problemas. Si usa patrones apropiados, no tendrá problemas. – LukLed

+1

@rwwilden: Hubo millones de preguntas sobre el reutilización de ObjectContext, aquí en SO y en otras páginas. El uso por solicitud parece dominar, no es solo mi opinión. – LukLed

1

Me gusta Lucas dice que esta pregunta se ha hecho muchas veces en SO.

Para una aplicación web, por ciclo de solicitud parece funcionar mejor. Singleton es definitivamente una mala idea.

Por solicitud funciona bien porque una página web tiene un usuario, tal vez algunos proyectos que pertenecen a ese usuario, tal vez algunos mensajes para ese usuario. Desea el mismo ObjectContext para que pueda ir a User.Messages para obtenerlos, tal vez marcar algunos mensajes como leídos, tal vez agregar un Proyecto y luego comprometer o abandonar todo el gráfico del objeto al completar el ciclo de la página.

+1

El singleton estático no solo es una mala idea, ¡también no es seguro para subprocesos! Un contexto creado debe usarse solo en un hilo. –

0

Última publicación aquí por 7 meses. Actualmente estoy abordando esta cuestión en mi aplicación y me inclino por la solución @LukLed al crear un ObjectContext único para la duración de mi HttpRequest. Para mi arquitectura, tengo varios controles que entran en la construcción de una página y todos estos controles tienen sus propios problemas de datos que extraen datos de solo lectura de la capa de EF. Parece un desperdicio para ellos crear y usar sus propios ObjectContext. Además, hay algunas situaciones en las que un control puede extraer datos del Contexto que podrían ser reutilizados por otros controles. Por ejemplo, en mi página maestra, mi encabezado en la parte superior de la página tiene información del usuario que los otros controles de la página pueden reutilizar.

Mi única preocupación es que pueda atraer entidades al contexto que afectará las consultas de otros controles. Aún no lo he visto, pero no sé si estoy buscando problemas. ¡Creo que ya veremos!

0
public class DBModel { 

     private const string _PREFIX = "ObjectContext"; 

     // DBModel.GetInstance<EntityObject>(); 
     public static ObjectContext GetInstance<T>() { 
      var key = CreateKey<T>(); 
      HttpContext.Current.Items[key] = HttpContext.Current.Items[key] ?? Activator.CreateInstance<T>(); 
      return HttpContext.Current.Items[key] as ObjectContext; 
     } 

     private static string CreateKey<T>() { 
      return string.Format("{0}_{1}", _PREFIX, typeof(T).Name); 
     } 
    } 
Cuestiones relacionadas