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

C# ObjectContext实例已被释放,不能再用于需要连接的操作。在参考表中,c#,asp.net,sql,entity-framework,asp.net-mvc-4,C#,Asp.net,Sql,Entity Framework,Asp.net Mvc 4,我有两个表客户和国家和使用(实体框架与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

我有两个表客户国家和使用(实体框架与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; }
 }
使用系统;
使用System.Collections.Generic;
公共部分类客户
{
公共int Id{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串地址{get;set;}
公共字符串电子邮件{get;set;}
公用字符串电话{get;set;}
公共可空CountrryId{get;set;}
公共字符串注释{get;set;}
公共虚拟国家{get;set;}
}
我尝试构建一个select查询,以获取具有国家/地区名称的所有客户。但我总是收到以下错误消息


在数据上下文被释放后,您正试图访问关联属性
国家/地区
。实体框架,默认情况下。换句话说,当您第一次尝试访问关联属性时,它会再次访问数据库。要访问数据库,实体框架必须使用数据上下文。在您的情况下,它将尝试使用由
jQGridDemoEntities db=new jQGridDemoEntities()
创建的数据上下文,不幸的是,该上下文已在您的代码中处理完毕。数据上下文已被释放,因为您已退出

您有三种解决此问题的方法:

  • 在数据上下文仍处于活动状态时访问关联属性。更具体地说,将访问关联属性的代码移动到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
    };
    

    • 您可以通过
      使用
      块来处理数据库

      使用
      block not outside将代码放入


      当使用
      使用
      块元素时,在
      使用(var元素)
      中,当使用块结束时,将释放该块元素

      您启用了延迟加载。所以,当您尝试加载引用属性时,并没有办法这样做,因为ObjectContext是在使用
      块之后处理的

      有两种方法可以解决此问题:

      //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
      ,也可以使用
      修复此问题。包括(c=>c.Country)

      还有一个解决方案,使用ViewBag

      using(var db = new jQGridEntities())
      {
          var customers = db.Customers.Where(c=>c.Country!=null).ToList();
          ViewBag.customerlist= customers;
      }
      

      返回后尝试使用
      关闭
      延迟加载
      可能对您的上下文启用,这意味着当您第一次尝试通过访问父上下文的属性读取其值时,将使用父上下文的连接从数据库加载
      国家/地区。@Mathew yes,其他部分已经是值了,因为
      ToList
      在那里,但是
      Country
      不是(即使在模型中,它是
      virtual
      getter去db的地方),谢谢FlyingFox编辑我的代码。这是我的第一篇帖子。否决选民,否决第一张海报上的错误答案是不礼貌的。对于这个问题,还有其他答案不仅是错误的,而且也是危险的well@PanagiotisKanavos虽然我不太喜欢否决票(当然也不赞成在-1或-2以下否决票),但我不同意第一次否决海报是不礼貌的。不管是谁发布的,一个糟糕的答案也同样糟糕。给人们一些折扣,因为这是他们的第一次尝试,这意味着如果人们是新来的,我们更喜欢糟糕的材料。我建议,当涉及到第一次的时候,我们应该花更多的时间来解释为什么答案不好(就像你一样)。@PanagiotisKanavos澄清——我认为我们不应该对海报的信用/历史进行严重的否决。然而,我知道,当一个新来者加入并投入2美分时,一些用户会感到沮丧,他们认真地认为这会让他们和精明的程序员结对。那是自大,应该受到严厉的惩罚,用棍子殴打。打个比方说。@KonradViltersten记得最基本的指令——“友善”。否则,第一次发布的海报将成为最后一次发布。延迟加载问题无法通过留下孤立的上下文来解决。事实上,它甚至不能解决这个问题,因为垃圾收集器可以在加载
      国家/地区
      属性之前随时处理上下文。因此,请确保您使用的是System.Data.Entity,否则VS会在第二个选项中抱怨lambda表达式。如果
      Include
      没有帮助,我还可以尝试什么?