2009-05-05 13 views
61

El objeto de contexto de Entity Framework implementa un método Dispose() que "Libera los recursos utilizados por el contexto del objeto". ¿Qué es lo que realmente hace? ¿Sería algo malo ponerlo siempre en una declaración de {} uso? Lo he visto usar tanto con y sin la declaración de uso.¿Debe el Contexto del marco de la entidad ingresar en la declaración de uso?

Específicamente voy a utilizar el contexto EF desde un método de servicio WCF, creo el contexto, hago un poco de linq y devuelvo la respuesta.

EDITAR: Parece que no soy el único que se pregunta sobre esto. Otra pregunta es qué está sucediendo realmente dentro del método Dispose(). Algunos dicen que cierra las conexiones, y algunos artículos dicen que no. ¿Cual es el trato?

Respuesta

32

Si crea un contexto, debe deshacerse de él más tarde. Si debe usar la instrucción using, depende del tiempo de vida del contexto.

  1. Si crea el contexto de un método y utilizarlo sólo dentro de este método, que realmente debe utilizar la instrucción using porque le da el control de excepciones sin ningún código adicional.

  2. Si se utiliza el contexto para un período más largo - que es el tiempo de vida no está obligado por el tiempo de ejecución de un método - no se puede utilizar la instrucción using y hay que llamar Dispose() ti mismo y tener cuidado de que siempre llámalo.

¿Qué hace Dispose() para un contexto de objeto?

No miré el código, pero al menos espero que cierre la conexión de la base de datos con sus sockets subyacentes o con los recursos que haya utilizado el mecanismo de transporte.

1

Siempre, si instancia una clase que implementa IDisposable, entonces usted es responsable de llamar a Dispose. En todos los casos menos uno, esto significa un usando el bloque.

+2

Es cierto, pero la cuestión es lo que hace el método Dispose() Relly para el contexto EF . ¡Parece que no es realmente tan importante por lo que puedo encontrar sobre el tema! –

+1

"Responsable" ... ¿No es solo para código no administrado? – ullmark

+3

Gracias por hacer esta pregunta. Como resultado, descubrí que todas las llamadas a Eliminar que me preocupa olvidar en nuestra aplicación podrían no ser tan críticas como me temía (leyendo http://lee.hdgreetings.com/2008/06/linq-datacontex. html). – BlueMonkMN

4

Dado que no sabe cuándo el recolector de basura dispone de un artículo, siempre es bueno envolver objetos que implementen IDisposable en un usando el bloque si sabe cuándo ha terminado con él.

1

Cuando deseche, el ObjectContext dispone otros objetos propios.

Incluye cosas como la EntityConnection que envuelve la conexión real de la base de datos, es decir, una conexión Sql.

Así que 'si' la conexión Sql está abierta, se cerrará cuando elimine el ObjectContext.

4

por Progamming Entity Framework: "Puede eliminar explícitamente el ObjectContext o esperar a que el recolector de basura haga el trabajo".

En resumen, aunque no se requiere la instrucción de uso, es recomendable si se completa el uso del ObjectContext, ya que el recurso se libera inmediatamente en lugar de esperar la recolección de elementos no utilizados.

+0

GC se hizo para ** no ** disponer cosas de forma explícita. Es imprescindible (si es posible) disponer los objetos que hacen referencia a los recursos no gestionados. Entonces, la verdadera pregunta aquí: ¿el contexto EF hace referencia a un recurso no administrado? Si no, entonces no debería disponer de él ... –

0

He notado (aunque en una sola aplicación) que la eliminación explícita causaba abortar las excepciones en mscorlib que están atrapadas antes del código de la aplicación, pero al menos en mi caso resulta en un golpe de rendimiento notable. No he hecho ninguna investigación significativa sobre el tema, pero probablemente algo que valga la pena considerar si estás haciendo esto. Simplemente mire su salida DEBUG para ver si está obteniendo el mismo resultado.

0

Si Dispose cierra la conexión a DB, es una mala idea llamarlo. Por ejemplo, en las conexiones ADO.NET están en el grupo de conexiones y nunca se cierran antes de que se agote el tiempo de espera o se detenga el grupo de aplicaciones.

1

realmente Probé esta cosa tanto para ADO.net y v.6 EF y vi conexiones en la tabla SQL

select * from sys.dm_exec_connections 

Métodos a ensayar veía así:

1) ADO.net con usando

using(var Connection = new SqlConnection(conString)) 
    { 
    using (var command = new SqlCommand(queryString, Connection)) 
    {  
     Connection.Open(); 
     command.ExecuteNonQueryReader(); 
     throw new Exception() // Connections were closed after unit-test had been 
     //finished. Expected behaviour 
    } 
    } 

2) ADO.net sin que usando

var Connection = new SqlConnection(conString); 
using (var command = new SqlCommand(queryString, Connection)) 
{ 
    Connection.Open(); 
    command.ExecuteNonQueryReader(); 
    throw new Exception() // Connections were NOT closed after unit-test had been finished 

    finished. I closed them manually via SQL. Expected behaviour 
    } 

1) EF con usar.

using (var ctx = new TestDBContext()) 
    { 
     ctx.Items.Add(item); 
     ctx.SaveChanges(); 
     throw new Exception() // Connections were closed, as expected. 

    } 

2) EF sin utilizar

var ctx = new TestDBContext();    
ctx.Items.Add(item); 
ctx.SaveChanges(); 
throw new Exception() // Connections WERE successfully closed, as NOT expected. 

No sé por qué es así, pero EF conexiones cerradas automáticamente. Además, todos los patrones de repositorio y UnitOfWork que usan EF no usan. Es muy extraño para mí, porque DBContext es de tipo Desechable, pero es un hecho.

Tal vez en Microsoft hicieron algo nuevo para el manejo?

+0

En realidad es simple: si no abre manualmente la conexión (como 'ctx.Database.Connection.Open();') EF6, cuídese y se encargará de abrir/cerrar con cada consulta (ver agrupación de conexiones ADO por qué no es una mala idea). Pero si lo abre manualmente, EF6 considerará que sabe lo que está haciendo y lo dejará abierto. –

+0

Usted no respondió sobre el tema de mi comentario. No hay una conexión abierta manualmente para EF. Todo pega en los comentarios en el código –

3

EF5 y antes de la versión

using { ... 
      // connecction open here. 

      ... 
      context.Blogs.Add(blog); 
      context.SaveChanges(); // query etc now opens and immediately closes 

      ... 
      context.Blogs.Add(blog); 
      context.SaveChanges(); // query etc now opens and immediately closes 
    } 

EF6 y después de la versión

using { 
     // connecction open here. 

     ... 
     context.Blogs.Add(blog); 
     context.SaveChanges(); 

     // The underlying store connection remains open for the next operation 

     ... 
     context.Blogs.Add(blog); 
     context.SaveChanges(); 

     // The underlying store connection is still open 

    } // The context is disposed – so now the underlying store connection is closed 

Referencia: http://msdn.microsoft.com/en-us/data/dn456849#open5

+1

Esto es incorrecto o engañoso. El artículo al que hizo referencia es sobre la gestión de la conexión, sobre la llamada MANUAL de 'connection.Open()' (y no lo traduce a su código de ejemplo), no sobre 'Dispose()'. Si no llama 'connection.Open()' manualmente (lo deja a la gestión de conexión EF), la conexión se cierra en su '// La conexión de la tienda subyacente todavía está abierta'. Nada que ver con la pregunta OP. –

Cuestiones relacionadas