ObjectContext 实例已被释放,不能再用于需要连接的操作。在参考表中

Posted

技术标签:

【中文标题】ObjectContext 实例已被释放,不能再用于需要连接的操作。在参考表中【英文标题】:The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. in Reference table 【发布时间】:2014-03-27 06:03:55 【问题描述】:

我有两个表 CustomersCountry 并使用(Entity Framework with vs 2012)

还有模型类

 using System;
 using System.Collections.Generic;

 public partial class Customer
 
     public int Id  get; set; 
     public string FirstName  get; set; 
     public string LastName  get; set; 
     public string Address  get; set; 
     public string Email  get; set; 
     public string Phone  get; set; 
     public Nullable<int> CountrryId  get; set; 
     public string Note  get; set; 

     public virtual Country Country  get; set; 
 

我尝试构建一个选择查询以获取所有具有国家名称的客户。但我总是收到以下错误消息。

【问题讨论】:

返回后尝试关闭using Lazy Loading 可能会为您的上下文启用,这意味着当您第一次尝试通过访问该属性来读取其值时,Country 是使用父上下文的连接从数据库加载的。 @Mathew 是的,其他部分已经是值,因为那里有 ToList,但 Country 不是(即使在模型中它是 virtual,getter 去数据库的地方) 【参考方案1】:

在释放数据上下文后,您正尝试访问关联属性 Country。实体框架,默认情况下,loads association properties lazily。换句话说,当您第一次尝试访问关联属性时,它会再次访问数据库。要访问数据库,Entity Framework 必须使用数据上下文。在您的情况下,它将尝试使用由 jQGridDemoEntities db = new jQGridDemoEntities() 创建的数据上下文,不幸的是,该上下文已在您的代码中被释放。由于您退出了using block,因此数据上下文已被释放。

您有三个选项来解决这个问题:

当数据上下文仍然存在时访问关联属性。更具体地说,将访问关联属性的代码移到 using 块中

按照我指定的第一个链接中的说明快速加载关联属性

customers = db.Customers.Include(c =&gt; c.Country).ToList()

当数据上下文仍然存在时,显式选择要从数据库返回的内容。并使用该信息构造您返回的 json 对象。

customers = db.Customers.Select(c => new

    c.Id,
    c.FirstName,
    c.LastName,
    c.Address,
    c.Email,
    c.Phone,
    CountryName = c.Country.Name,
    c.Note
;

【讨论】:

还要确保您使用的是 System.Data.Entity 否则 VS 会抱怨第二个选项中的 lambda 表达式。【参考方案2】:

您已启用延迟加载。因此,当您尝试加载引用属性时,没有办法做到这一点,因为 ObjectContext 在 using 块之后被释放。

有两种修复方法:

//1. Tell EF to load Country property immediately.
using(var db = new jQGridEntities())

    customers = db.Customers.Include(c => c.Country).ToList();


//2. Put return inside using block.
using(var db = new jQGridEntities())

    customers = db.Customers.ToList();
    return Json(/*your code*/);

你也可以禁用延迟加载,但在这种情况下你会得到NullReferenceException,这也可以使用.Include(c =&gt; c.Country)来修复。

【讨论】:

如果Include 没有帮助,我还能尝试什么?【参考方案3】:

你通过using块配置数据库

将您的代码放入using 块而不是外部。

当使用using块元素时,在using(var element)使用块结束时被释放

【讨论】:

延迟加载问题并不能通过留下孤立的上下文来解决。事实上,它甚至无法解决这个问题,因为垃圾收集器可以在没有时间加载Country 属性之前随时释放上下文【参考方案4】:

还有另一种解决方案,使用 ViewBag

using(var db = new jQGridEntities())

    var customers = db.Customers.Where(c=>c.Country!=null).ToList();
    ViewBag.customerlist= customers;

【讨论】:

感谢 FlyingFox 编辑我的代码。这是我的第一篇文章。 投反对票的人,对第一张海报的错误答案投反对票是不礼貌的。这个问题还有其他答案不仅错误而且很危险 @PanagiotisKanavos 虽然不喜欢投反对票(而且绝对不赞成投低于 -1 或 -2),但我不同意投反对票是不礼貌的首次发帖。一个糟糕的答案同样糟糕,无论是谁发布的。并且给人们某种折扣,因为这是他们的第一次尝试,这意味着如果人们是该网站的新手,我们会偏爱糟糕的材料。对于初学者,我建议我们花更多时间解释原因答案不好(就像您所做的那样)。 @PanagiotisKanavos 澄清一下——我认为我们不应该大力反对,不管发帖人的信用/历史如何。但是,我知道有些用户在新人加入并投入 2 美分认真相信这使他们与精明的程序员配对时感到沮丧。这简直太傲慢了,应该受到棍子殴打的极大惩罚。形象地说。 @KonradViltersten 记住主要指令 - “做个好人”。否则第一次发帖会变成最后一次发帖

以上是关于ObjectContext 实例已被释放,不能再用于需要连接的操作。在参考表中的主要内容,如果未能解决你的问题,请参考以下文章

此 ObjectContext 实例已释放,不可再用于需要连接的操作。

如何使用实体框架构建基于 3 个表的 JSON

C# 实体框架每个 HttpContext 仅使用一个 ObjectContext

EF DbContext 和 ObjectContext 转换

为什么不能直接调用DbContext.ObjectContext 获取属性呢?

向下转换 ObjectContext 到实体集合