Подтвердить что ты не робот

System.ObjectDisposedException: экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих подключения

Я использую EF 4 для извлечения списка сотрудников.

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);
}

Список извлекается OK, но когда я его сериализую, я получаю это исключение;

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)

Я нахожу это очень странным. Я уже получил список сотрудников, и DataContext был удален. Так почему я должен получить эту ошибку?

4b9b3361

Ответ 1

Похоже, что у вас есть некоторые лениво загруженные свойства отношений, которые еще не загружены (что связано с проблемой производительности n + 1). Вы можете попробовать нетерпеливо загружать, чтобы узнать, помогает ли это; в противном случае явно загружать данные для каждого элемента в списке, прежде чем закрыть объект-контекст.

Ответ 2

Вы можете отключить ленивую загрузку, чтобы решить эту проблему.
Внутри блока "использование" попробуйте следующее:

yourObjectContext.ContextOptions.LazyLoadingEnabled = false;

После этого я смог сериализовать POCO EF (DbContext-POCO) в JSON без каких-либо проблем.

* Примечание: Поскольку я отключил ленивую загрузку... Я явно втягиваю связанные объекты, которые мне нужны раньше времени (в основном с .Include() в моем запросе) до того, как объект сериализуется в JSON.

Ответ 3

Думал, что я буду звонить здесь с моими 2 центами. У нас был очень большой уровень доступа к данным, и один из программистов использовался для использования оператора using для контекста:

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

Мы используем EntityConnection как статическое свойство, которое обслуживает dbContext для текущего HttpContext. Любой метод, вызванный после использования его блока, будет вызывать исключение "экземпляр ObjectContext был удален", поскольку, очевидно, контекст был удален после вызова метода. Поэтому, если вы используете только один контекст объекта для HttpContext, убедитесь, что вы не разрешаете сборщику мусора избавиться от него с помощью используемого блока.

Я решил, что я бы бросил это в ответах, так как я знаю, что многие люди используют контекст сущности по-разному, и я вижу много использования блоков в образцах кода.

Ответ 4

Я предпочитаю просто загружать жирный экземпляр, объявленный вне использования

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

Тогда я могу передать ее на Вид или любой помощник действительно хотел ее.

Ответ 5

Похоже, что происходит какая-то ленивая загрузка или замедленная оценка; вы не можете предположить, что объекты "загружены", пока вы на самом деле не попытаетесь прочитать их.

Вам нужно поддерживать DataContext, пока вы полностью не обработаете объекты, извлеченные из базы данных, чтобы избежать этих ошибок.

Ответ 6

У меня была такая же проблема и я мог решить ее, выбрав проекцию объекта только с свойствами, требуемыми вызывающим, вместо того, чтобы возвращать полный объект. Похоже, что когда у вас много отношений в вашем объекте, сериализатор пытается их перемещать.

Итак, (предположим, что ваш объектный контекст называется "Entities" ), я бы попробовал что-то вроде этого:

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

        return employeeProjection;
 }

Ответ 7

Мне стоит взглянуть на ваш объект Employee и убедиться, что у вас нет виртуальных ключевых слов, торчащих там. Виртуальное ключевое слово интерпретируется Entity Framework как "ленивая загрузка". Нам нужно, чтобы ваш класс Employee сделал абсолютное утверждение, почему вы можете видеть исключение.

Ответ 8

У меня была вариация этой проблемы. Контекст данных не был закрыт, но экземпляр контекста объекта был удален, а ошибка все равно была отброшена.

Оказалось, что объект имеет собственный референтный внешний ключ (т.е. внешний ключ относится к той же таблице). Получив доступ к свойству навигации, когда он ссылается на нуль, вы получаете исключение objectcontext, исключающее, например, исключение нулевого указателя.

например:

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

Ответ 9

Я нашел лучший способ справиться с этим и сохранить инструкцию using, которую вам просто нужно использовать include, см. пример ниже:

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