ObjectContext实例已被释放,无法再使用

时间:2015-06-09 23:22:13

标签: c# asp.net-mvc entity-framework dispose

我已经看过这个问题一百万次,但我遇到的每一个建议我似乎已经覆盖了。

我的MVC解决方案中有实体框架,我有一个'存储库',它试图检索MyObject s的集合:

public static List<MyObject> GetMyObjects()
{
   using (var context = new MyEntities())
   {
       return context.MyObjects.Include("Contact").OrderByDescending(o => o.Date).ToList();
   }
}

我将此方法称为控制器操作的一部分,该操作尝试将其序列化:

public JsonResult All()
{
   return Json(MyRepository.GetMyObjects(), JsonRequestBehavior.AllowGet);
}

我收到以下错误:

ObjectContext实例已被处理,不能再用于需要连接的操作。

我不知道在哪里打开这个,我感谢实体框架'lazy-loads'关系数据集,如果需要它们,我很欣赏尝试序列化整个集合确实会尝试加载这些(在使用声明之外),但我在那里有'包含'。

我尝试过什么

我已经尝试了'include',我也确保没有其他关联是MyObject类的一部分(即我没有其他Include()来写。)

3 个答案:

答案 0 :(得分:5)

要避免这种情况,您可以选择一些选项。不要将导航属性声明为virtual或禁用上下文中的延迟加载行为。默认情况下启用延迟加载,通过创建派生代理类型的实例,然后覆盖virtual属性以添加加载挂钩来实现。因此,如果您想使用序列化程序,我建议您关闭延迟加载:

public class YourContext : DbContext 
{ 
    public YourContext() 
    { 
        this.Configuration.LazyLoadingEnabled = false; 
    } 
}

这些链接可以帮助您更好地理解我在答案中解释的内容:

如果从导航属性中删除virtual关键字,则POCO实体不符合第二个链接中描述的要求,因此,EF不会创建代理类来延迟加载导航属性。但是,如果禁用延迟加载,即使导航属性为virtual,也不会在任何实体中加载它们。在使用序列化程序时禁用延迟加载是个好主意。大多数序列化程序通过访问类型实例上的每个属性来工作。

作为第三个选项,您可以在导航属性上使用JsonIgnore属性,不希望将其序列化为实体的一部分,但正如我之前所说,最好的选择是禁用延迟加载。

答案 1 :(得分:0)

当您使用Include并使用Lazy加载,并将dbContext包装在Using语句中时,一旦尝试获取链接对象,dbContext就已经被释放。 您可以尝试急切加载导航属性,如下所示:

IQueryable<MyObjects> query = db.MyObjects.Include(m => m.Contact);

或者您可以取出Using语句,因为它限制了您的延迟加载...

答案 2 :(得分:0)

我遇到了同样的问题并在下面解决了;

我创建了一个新对象,并在从db获取对象后放置我将要使用的值。

示例代码:

 var listFromDb= db.XTable.Where(x => x.Id > 5).ToList();

 var list = new List<Package>();

 foreach (var item in listFromDb)
 {
     var a = new Package()
     {
          AccountNo = item.AccountNo,
          CreateDate = item.CreateDate,
          IsResultCreated = item.IsResultCreated,
        };
        list.Add(a);
      }