【问题标题】:Exception of type 'System.ObjectDisposedException'“System.ObjectDisposedException”类型的异常
【发布时间】:2012-07-25 11:17:06
【问题描述】:

我有以下 EF 代码第一个代码。它工作正常。但是当我寻找“club2.Members”的价值时,它会说:

“club2.Members”引发了“System.ObjectDisposedException”类型的异常。

消息是:

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

我没有为 Members 属性设置值。没关系。但是,它不应该在内部引起任何异常。

  1. 有没有办法克服这个异常?
  2. 删除此异常是否有助于提高性能?
  3. 为什么这个异常没有导致程序执行终止?

注意:我不需要俱乐部实体中的会员数据(在我打电话的地方)。即使当时还没有会员加入俱乐部。我只需要摆脱异常;不要使用急切加载来加载数据。如何避免异常

namespace LijosEF
{

public class Person
{
    public int PersonId { get; set; }
    public string PersonName { get; set; }
    public virtual ICollection<Club> Clubs { get; set; }
}

public class Club 
{
    public int ClubId { get; set; }
    public string ClubName { get; set; }
    public virtual ICollection<Person> Members { get; set; }

}




//System.Data.Entity.DbContext is from EntityFramework.dll
public class NerdDinners : System.Data.Entity.DbContext
{

    public NerdDinners(string connString): base(connString)
    { 

    }

    protected override void OnModelCreating(DbModelBuilder modelbuilder)
    {
         //Fluent API - Plural Removal
        modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }

    public DbSet<Person> Persons { get; set; }
    public DbSet<Club> Clubs { get; set; }



}
}




    static void Main(string[] args)
    {
        Database.SetInitializer<NerdDinners>(new MyInitializer());

        CreateClubs();
        CreatePersons();

    }

    public static void CreateClubs()
    {

        string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
        using (var db = new NerdDinners(connectionstring))
        {

            Club club1 = new Club();
            club1.ClubName = "club1";

            Club club2 = new Club();
            club2.ClubName = "club2";

            Club club3 = new Club();
            club3.ClubName = "club3";

            db.Clubs.Add(club1);
            db.Clubs.Add(club2);
            db.Clubs.Add(club3);

            int recordsAffected = db.SaveChanges();


        }
    }

    public static Club GetClubs(string clubName)
    {
        string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
        using (var db = new NerdDinners(connectionstring))
        {

            var query = db.Clubs.SingleOrDefault(p => p.ClubName == clubName);
            return query;
        }
    }

    public static void CreatePersons()
    {
        string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
        using (var db = new NerdDinners(connectionstring))
        {

            Club club1 = GetClubs("club1");
            Club club2 = GetClubs("club2");
            Club club3 = GetClubs("club3");

             //More code to be added (using db) to add person to context and save
        }
    }

【问题讨论】:

  • 我只是忽略了你的代码。为什么要在 CheckValues 中创建另一个 db 实例?
  • @AmiramKorach 我有另一种方法 - CreatePersons。我将不得不在那里使用新的上下文。我正在使用每个请求的上下文方法。人们需要了解俱乐部。
  • 这段代码没有意义。您根本没有在 CreatePersons 中使用 db 变量。每个 GetClubs 调用都使用自己的 db 变量。
  • @AmiramKorach。将在 CreatePersosns 方法(使用 db)中添加更多代码以将人员添加到上下文并保存
  • 好的。只需确保您没有在来自不同上下文的实体之间建立联系。

标签: c# .net entity-framework ef-code-first


【解决方案1】:

您收到此错误是因为您在执行查询后释放了 dbcontext。如果要使用“成员”中的数据,请使用查询加载它: http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx

如果您不需要延迟加载,这意味着只加载您在查询中加载的数据(这将消除异常),请设置 LazyLoadingEnabled = false。看这里: Disable lazy loading by default in Entity Framework 4

【讨论】:

  • 我不需要俱乐部实体中的会员数据(在我打电话的地方)。即使在那个时候也没有成员添加到俱乐部。我只需要摆脱异常;不加载数据。如何避免异常?
【解决方案2】:

方法 1

不需要下面的方法。这可以在当前上下文中完成。这只是一个选择。

GetClubs("club1");

方法 2

附加实体解决了问题:

            Club club1 = GetClubs("club1");
            Club club2 = GetClubs("club2");
            Club club3 = GetClubs("club3");

            ((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)club1);
            ((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)club2);
            ((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)club3);


            var test = club2.Members;

我不应该尝试引用 club2.Members(属于 Club 类),因为创建 Person 对象不需要它。

Members 是 Club 类中的相关数据。由于它是虚拟的,它会做延迟加载。

在不同的场景中,如果我必须从不同的上下文中检索 Members 对象(这是一个相关数据),我应该依赖预先加载(在为您提供 Club 对象的地方)。

另请参阅以下内容:

  1. Entity Framework: Duplicate Records in Many-to-Many relationship

  2. System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

  3. The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

  4. ObjectContext instance has been disposed while binding

【讨论】:

  • @AmiramKorach 您如何看待这种方法?
  • 坚持阿米拉姆的建议。这仅在您将实体重新附加到新上下文时才有效。我认为在您的情况下,您想使用 Include 进行急切加载。每次要访问导航属性时都打开新的上下文不是一个好主意。请记住,因为您将导航属性标记为虚拟,所以 EF 将返回一个动态代理,该代理在释放上下文时将不起作用。在关闭上下文之前返回您需要的所有数据将解决问题。
  • 我认为这很危险。正如我上面评论的那样,我认为根本不需要在 CheckValues 中打开一个新的上下文。此外,我不会尝试将实体附加到多个上下文。我不确定您是否会为此获得例外。
  • @JaySilk84 我认为,急切加载是为了检索相关数据。在我的场景中,我没有检索相关数据 - 我只是设置相关数据(俱乐部是人员的相关数据)。我不认为,急切的加载是必要的。你怎么看?
  • @Lijo 如果您不需要数据,请不要访问导航属性。在上述情况下,仅当您尝试扩展 Members 属性时,调试器中才会出现异常。如果您从不访问该属性,则不会在运行时引发该异常。如果您永远不需要查看俱乐部中的所有成员 (Club.Members),而只需要一个人所属的俱乐部 (Person.Clubs),那么只需从 Club 中删除 Members 导航属性。您不需要映射模型中的所有属性或关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
  • 2012-02-06
  • 2011-04-20
  • 2013-08-13
  • 1970-01-01
  • 2022-12-06
  • 2021-01-17
相关资源
最近更新 更多