【问题标题】:System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connectionSystem.ObjectDisposedException:ObjectContext 实例已被释放,不能再用于需要连接的操作
【发布时间】:2011-05-11 12:50:41
【问题描述】:

我正在使用 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);
}

列表检索正常,但是当我序列化它时,我得到了这个异常;

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 已被释放。那么为什么会出现这个错误呢?

【问题讨论】:

  • 你能提供完整的堆栈跟踪吗?

标签: c# asp.net json


【解决方案1】:

听起来您有一些尚未加载的延迟加载的关系属性(具有相关的“n+1”性能问题)。您可以尝试eager loading 看看是否有帮助;否则,在关闭对象上下文之前显式加载列表中每个项目的数据。

【讨论】:

  • 我想保持延迟加载并过滤掉我不需要的对象。我认为从您的回答来看,由于延迟加载而将对象保留为空,因此序列化不起作用。我可以创建一个只包含我想要的属性的类,并从中创建一个列表。我想知道是否有更好的方法,我不需要创建这样的类?
  • @arame3333 - 既然你在谈论 JavaScriptSerializer,匿名类型会很好 - 只是 select new { row.Foo, row.Bar }
  • 您能否详细说明“否则,显式加载列表中每个项目的数据”?谢谢。
【解决方案2】:

您可以关闭延迟加载来解决此问题。
在你的“使用”块中,试试这个:

yourObjectContext.ContextOptions.LazyLoadingEnabled = false;

完成此操作后,我能够毫无问题地将我的 EF(DbContext 生成)POCO 序列化为 JSON。

*注意:由于我已关闭延迟加载...在对象序列化为 JSON 之前,我会提前明确拉入我需要的相关对象(主要是在我的查询中使用 .Include())。

【讨论】:

  • 干净简单的解决方案,但请注意,这种方法不会自动加载相关对象(子对象)。
  • 我认为代码必须是:yourObjectContext.Configuration.LazyLoadingEnabled = false; EF6 方式。
【解决方案3】:

我以为我会用我的 2 美分在这里插话。我们有一个非常大的数据访问层,其中一位程序员习惯于对上下文使用 using 语句,如下所示:

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

我们将 EntityConnection 用作静态属性,它为每个当前 HttpContext 提供一个 dbContext。在他的 using 块之后调用的任何方法都会抛出异常“ObjectContext 实例已被释放”,因为显然上下文是在他的方法调用之后被释放的。因此,如果每个 HttpContext 只使用一个实体上下文,请确保不允许垃圾收集器使用 using 块来处理它。

我想我会把这个放在答案中,因为我知道很多人以不同的方式使用实体上下文,而且我在代码示例中看到了很多 using 块。

【讨论】:

  • Mario +1 这是我遇到的问题。我使用 EF 根据在搜索框中键入的字母获取自动建议。我尝试使用 using{} 块但收到此错误。现在我只使用一个实例,但不确定正确的处理方式。你能提供什么建议吗?
【解决方案4】:

我更喜欢只加载一个在 using 之外声明的胖实例

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

然后我可以将她传递到 View 或任何助手真正想要她的地方..

【讨论】:

    【解决方案5】:

    这听起来像是发生了一些延迟加载或延迟评估;在您实际尝试读取对象之前,您不能假设对象已“加载”。

    您需要维护您的DataContext,直到您完全处理完从数据库中检索到的对象以避免这些错误。

    【讨论】:

      【解决方案6】:

      我遇到了同样的问题,可以通过选择仅具有调用者所需属性的对象投影来解决它,而不是返回完整的对象。 似乎当您的对象中有许多关系时,序列化程序会尝试导航这些关系。

      所以,(假设你的对象上下文被称为“实体”)我会尝试这样的事情:

      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 对象,并确保您没有任何虚拟关键字突出。 virtual 关键字被实体框架解释为“延迟加载”。我们需要查看您的 Employee 类,以绝对断言您为什么会看到异常。

        【讨论】:

          【解决方案8】:

          我对这个问题有不同的看法。数据上下文未关闭,但对象上下文实例已被处理,仍然抛出错误。

          原来该对象有一个自引用外键(即外键引用回同一个表)。当导航属性引用 null 时访问它,您会得到 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 语句,请参见下面的示例:

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

            【讨论】:

              【解决方案10】:
              using (EmployeeContext db= new EmployeeContext())
                  {
                      var lst = db.Employees.Select(p=> new {
                          EmployeeID = p.EmployeeID,
                          Name = p.Name,
                          Salary = p.Salary,
                          Position = p.Position,
                          Age = p.Age,
                          Office = p.Office
                      }).ToList();
                      return Json(lst, JsonRequestBehavior.AllowGet);
                  }
              

              【讨论】:

                猜你喜欢
                • 2012-07-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多