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 【问题描述】:我有两个表 Customers 和 Country 并使用(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 => 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 => 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 实例已释放,不可再用于需要连接的操作。
C# 实体框架每个 HttpContext 仅使用一个 ObjectContext
EF DbContext 和 ObjectContext 转换