2010-11-17 22 views
25

Estoy utilizando EF 4 para recuperar una lista de empleados.System.ObjectDisposedException: la instancia de ObjectContext se ha eliminado y ya no se puede usar para las operaciones que requieren una conexión

public ContentResult AutoCompleteResult(string searchText) 
{ 
    List<Employee> list = Employee.GetAllCurrentEmployees(); 
    List<Employee> filteredEmployees = list 
     .Where(x => x.GetName().ToLower().Contains(searchText.ToLower())) 
     .ToList(); 

    JavaScriptSerializer jsonSerializer = new JavaScriptSerializer(); 
    var jsonString = jsonSerializer.Serialize(filteredEmployees).ToString(); 
    return Content(jsonString); 
} 

La lista se recupera bien, pero cuando la serializo, obtengo esta excepción;

System.ObjectDisposedException: The ObjectContext instance has been 
disposed and can no longer be used for 
operations that require a connection. 
    Generated: Wed, 17 Nov 2010 16:06:56 GMT 

System.ObjectDisposedException: The ObjectContext instance has been 
disposed and can no longer be used for operations that require a connection. 
at 
System.Data.Objects.ObjectContext.EnsureConnection() 
at 
System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)  at 
System.Data.Objects.ObjectQuery`1.Execute(MergeOption mergeOption)  at 
System.Data.Objects.DataClasses.EntityCollection`1.Load(List`1 collection, MergeOption mergeOption) at 
System.Data.Objects.DataClasses.EntityCollection`1.Load(MergeOption mergeOption)  at 
System.Data.Objects.DataClasses.RelatedEnd.Load() at 
System.Data.Objects.DataClasses.RelatedEnd.DeferredLoad() at 
System.Data.Objects.DataClasses.EntityCollection`1.System.Collections.IEnumerable.GetEnumerator() at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat 
serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat 
serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat 
serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object 
o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat 
serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, 
SerializationFormat 
serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat 
serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object 
o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat 
serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object 
obj, StringBuilder output, SerializationFormat serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object 
obj, SerializationFormat serializationFormat)  at 
System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj)  at 
SHP.Controllers.EmployeeController.AutoCompleteResult(String searchText) in C:\Documents and Settings\geoffreypayne\My Documents\Visual Studio 
2010\Projects\MVC\SHP\SHP\Controllers\EmployeeController.cs:line 
623  at lambda_method(Closure , ControllerBase , Object[])  at 
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) at 
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext 
controllerContext, IDictionary`2 parameters)  at 
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext 
controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)  at 
System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.InvokeActionMethodWithFilters>b__a() 
at 
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter 
filter, ActionExecutingContext preContext, Func`1 continuation)  
at 
System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<>c__DisplayClassf.<InvokeActionMethodWithFilters>b__c() at 
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)  at 
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext 
controllerContext, String actionName) 

Me parece muy extraño. Ya he recuperado la lista de empleados y se ha eliminado el DataContext. Entonces, ¿por qué debería obtener este error?

+1

¿Puede dar la pila completa ¿rastro? –

Respuesta

22

Parece que tiene algunas propiedades de relación de carga diferida que aún no se han cargado (que tiene un problema de rendimiento "n + 1" asociado). Puede probar eager loading para ver si esto ayuda; de lo contrario, cargue explícitamente los datos de cada elemento en la lista, antes de, cierre el contexto del objeto.

+0

Quería mantener la carga lenta y filtrar los objetos que no necesito. Creo que a juzgar por su respuesta, la serialización no funciona debido a objetos que quedan como nulos debido a la carga diferida. Podría crear una clase con solo las propiedades que quiero y crear una lista a partir de eso. Me pregunto si hay una mejor manera, que no necesito crear una clase así. – arame3333

+2

@ arame3333 - ya que está hablando de 'JavaScriptSerializer', un tipo anónimo funcionaría muy bien, simplemente' seleccione nuevo {row.Foo, row.Bar} 'etc –

+1

¿Puede explicar más detalladamente" de lo contrario, cargue explícitamente los datos de cada uno? elemento en la lista "? Gracias. – PeterX

1

Suena como una evaluación de carga diferida o demorada que está sucediendo; no puede suponer que los objetos están "cargados" hasta que realmente intente leer de ellos.

Debe mantener su DataContext hasta que haya terminado de manejar los objetos recuperados de la base de datos para evitar estos errores.

1

Tuve el mismo problema y pude resolverlo seleccionando una proyección del objeto con solo las propiedades requeridas por la persona que llama, en lugar de devolver el objeto completo. Parece que cuando tiene muchas relaciones en su objeto, el serializador intenta navegar por ellas.

Por lo tanto, (suponiendo que el contexto del objeto se llama "Entidades") que me gustaría probar algo como esto:

Pensamiento
using (Entities context = new Entities()) 
{ 
     var employeeProjection = (from e in context.Employee 
         select new { e.Id, c.FirstName, e.LastName }).ToList(); 

     return employeeProjection; 
} 
12

me interrumpiría aquí con mis 2 centavos. Tuvimos una capa de acceso a datos muy grande, y uno de los programadores se utilizó para el uso de una declaración utilizando para el contexto de esta manera:

using (EntityModel myContext = EntityConnection) 
{ 
    //code in here to grab data 
} 

Estamos utilizando el EntityConnection como una propiedad estática que sirve una dbContext por corriente HttpContext. Cualquier método llamado después de su bloque de uso arrojaría la excepción 'La instancia de ObjectContext ha sido eliminada' ya que obviamente el contexto fue descartado después de su llamada al método. Entonces, si solo está utilizando un contexto de entidad por HttpContext, asegúrese de no permitir que el recolector de basura lo elimine mediante el uso de un bloque.

Pensé que arrojaría esto en las respuestas ya que sé que mucha gente usa el contexto de la entidad de manera diferente y veo un montón de uso de bloques en muestras de código.

+2

Mario +1 este es el problema con el que me estaba encontrando. Estoy usando EF para obtener autosugerencias basadas en la letra escrita en un cuadro de búsqueda. Intenté usar un bloque {} que usaba pero estaba obteniendo este error. ahora solo uso una sola instancia pero no estoy seguro de la forma correcta de eliminación. ¿podrías ofrecer algún consejo? – Shannow

2

prefiero simplemente carga una instancia de grasas declarado fuera de la usando

Customer _custObj; 
     using (RazorOne rz1 = new RazorOne()) 
     { 
      _custObj = rz1.Customers.FirstOrDefault();  // .Include = Lazy loading 
      // Versus Implicit Load 
      _custObj.AddressReference.Load(); 
      _custObj.Address1Reference.Load(); 
     } 

Entonces puede pasar a su a la vista o lo que sea de ayuda realmente la quería ..

14

Usted puede desactivar perezoso cargando para resolver este problema
Dentro de su bloque de 'utilizar', intente esto:

yourObjectContext.ContextOptions.LazyLoadingEnabled = false; 

Después de hacer esto, yo era capaz de serializar mi EF (DbContext-generada) POCO a JSON sin ningún problema.

* Nota: Desde que desactivé la carga diferida ... explícitamente recojo los objetos relacionados que necesito con anterioridad (principalmente con .Include() en mi consulta) antes de que el objeto se serialice en JSON.

+1

Solución limpia y simple, pero tenga en cuenta que con este enfoque los objetos relacionados (objetos secundarios) no se cargan automáticamente. –

+2

Creo que el código debe ser: 'yourObjectContext.Configuration.LazyLoadingEnabled = false;' en formato EF6. –

0

Merece la pena echar un vistazo a su objeto Employee y asegurarse de que no haya ninguna palabra clave virtual que sobresalga. La palabra clave virtual es interpretada por Entity Framework como 'lazy-load'. Tendríamos que ver a su clase Empleado para hacer una afirmación absoluta de por qué podría estar viendo la excepción.

0

Tuve una variación en este problema. El contexto de datos no se cerró, pero la instancia de contexto de Objeto se eliminó. El error se produjo de todos modos.

Resultó que el objeto tenía una clave externa autorreferencial (es decir, la clave externa referida a la misma tabla). Al acceder a la propiedad de navegación cuando se refiere a un nulo, se obtiene la excepción de objectcontext dispuesta en lugar de, por ejemplo, una excepción de puntero nulo.

por ejemplo:

var a = myObject.Name; // works because myObject still has open object context 
var b = myObject.SelfReference; // throws objectcontext disposed if SelfReference is null 
0

He encontrado la mejor manera de manejar esto y mantener la instrucción using sólo tiene que utilizar la incluyen, vea el ejemplo a continuación:

using (var ctx = new Context(this.connectionString)) { 
    var query = ctx.[maintable] 
    .Include(x => x.[theothertable]) 
    .FirstOrDefaultAsync(u => u.UserName.Equals(userName)); 
} 
Cuestiones relacionadas