System.ObjectDisposedException:ObjectContext实例已被释放,不能再用于需要连接的操作

时间:2010-11-17 16:25:36

标签: c# asp.net json

我使用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。那么为什么我会收到这个错误?

10 个答案:

答案 0 :(得分:23)

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

答案 1 :(得分:17)

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

yourObjectContext.ContextOptions.LazyLoadingEnabled = false;

执行此操作后,我能够将我的EF(DbContext生成的)POCO序列化为JSON而没有任何问题。

*注意:因为我已经关闭了延迟加载...在将对象序列化为JSON之前,我明确地提取了我需要的相关对象(在我的查询中主要使用.Include())。

答案 2 :(得分:12)

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

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

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

我想我会把这个放在答案中,因为我知道很多人使用不同的实体上下文,我看到很多代码样本中都使用了块。

答案 3 :(得分:2)

我更喜欢只加载在using

之外声明的fat实例
   Customer _custObj;
        using (RazorOne rz1 = new RazorOne())
        {
             _custObj = rz1.Customers.FirstOrDefault();      //  .Include = Lazy loading
            // Versus Implicit Load
            _custObj.AddressReference.Load();
             _custObj.Address1Reference.Load();
        }

然后我可以将她传递给View或任何帮助者真正想要她......

答案 4 :(得分:1)

这听起来像正在发生的一些延迟加载或延迟评估;在你真正尝试从中读取对象之前,你不能假设对象被“加载”。

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

答案 5 :(得分:1)

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

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

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

        return employeeProjection;
 }

答案 6 :(得分:0)

我值得一看你的Employee对象,并确保你没有任何虚拟关键字。虚拟关键字由实体框架解释为“延迟加载”。我们需要看到你的Employee类做出绝对的断言,为什么你会看到异常。

答案 7 :(得分:0)

我对这个问题有所了解。数据上下文没有关闭,但是对象上下文实例已经被处理了,无论如何都会抛出错误。

事实证明,该对象具有自引用外键(即外键引用回同一个表)。当它引用null时访问导航属性,就会得到objectcontext disposing异常,而不是空指针异常。

例如:

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

答案 8 :(得分:0)

我找到了处理此问题的最佳方法,并保留使用include语句所需的using语句,请参阅下面的示例:

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

答案 9 :(得分:0)

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