Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ObjectContext has been disposed throwed by EnsureConnection() in consecutive queries (No navigation properties used and no using())

Somehow EF disposes the ObjectContext in between two queries, without any further notice, but apparently not randomly and not due to a timeout.

I added the using so the example is self contained but it does the same with the DbContext used in the whole application.

using (MyDbContext db = new MyDbContext ())
{
  //I am sure these are unique
  Employee emp = db.Employees.Single(e => e.FirstName == "Bob" && e.LastName == "Morane");
  Node node = db.Nodes.Single(n => n.ShortName == "stuff"); //Here the request throws
  // "ObjectContext instance has been disposed and can no longer be used for operations that require a connection"
}

Notice db is not yet disposed by using so this is out of the question. The error also happens with .First() and .Where().Single/First().

Inverting the two requests does not do the trick:

using (MyDbContext db = new MyDbContext ())
{
  Node node = db.Nodes.Single(n => n.ShortName == "stuff");
  Employee emp = db.Employees.Single(e => e.FirstName == "Bob" && e.LastName == "Morane"); //Here the request throws
  // "ObjectContext instance has been disposed and can no longer be used for operations that require a connection"
}

I do not use any navigation propery of Employee either, and this does not solve the problem:

using (MyDbContext db = new MyDbContext ())
{
  // According to every post I've found this "should fix the objectcontext disposed error"
  db.Configuration.ProxyCreationEnabled = false;
  db.Configuration.LazyLoadingEnabled = false;

  Employee emp = db.Employees.Single(e => e.FirstName == "Bob" && e.LastName == "Morane");
  Node node = db.Nodes.Single(n => n.ShortName == "stuff"); //But it doesn't: same error here
}

What I have noted is this problem doesn't occur on the WebSite project but only in the UnitTests project. I have set the same connectionString for the two (apart from the db name) but that didn't do anything either.

Worse yet :

using (MyDbContext db = new MyDbContext ())
{
  Node node = db.Nodes.Single(n => n.ShortName == "stuff");
  Employee emp = db.Employees.Single(e => e.FirstName == "Bob" && e.LastName == "Morane"); // boom
  node.Should().NotBeNull();
}

using (MyDbContext db = new MyDbContext ())
{
  Node node = db.Nodes.Single(n => n.ShortName == "stuff");
  node.Should().NotBeNull();
  Employee emp = db.Employees.Single(e => e.FirstName == "Bob" && e.LastName == "Morane"); // no boom
}

The timeout is set to 20000 and MultipleActiveResultSets is set to true.

For now the only workaround I found was to call .ToList() on the whole DbSet before trying .Single():

using (MyDbContext db = new MyDbContext ())
{
  Employee emp = db.Employees.Single(e => e.FirstName == "Bob" && e.LastName == "Morane");
  Node node = db.Nodes.ToList().Single(n => n.ShortName == "stuff"); //Works
}

But this isn't acceptable because the operation is frequent and I expect the DbSet to be quite big so this will take a lot of time for nothing.

like image 628
Eregrith Avatar asked Nov 12 '22 20:11

Eregrith


1 Answers

well, as we (with more effort by Eregrith) found out, it was the EF which was doing manipulations with context before sending it to test initializer so that it was functioning unexpectedly ; by implementing basic create/seed/delete instead of initializer the exception was gone. (in my opinion, it still needs more detailed investigation of what actually happens there =] )

The test initializer was called like this:

System.Data.Entity.Database.SetInitializer<MyDbContext>(new DatabaseTestInitializer());

DatabaseTestInitializer:

public class DatabaseTestInitializer : DropCreateDatabaseAlways<MyDbContext>
{
    protected override void Seed(MyDbContext context)
    {
        SeederHelper.Seed(context);
    }
}

Removing the call to SetInitializer<> solved the problem.

In base class UnitTest:

[SetUp]
protected virtual void Initialize()
{

  ContainerBuilder builder = new ContainerBuilder();
  this.RegisterTypes(builder);
  this.Container = builder.Build();

  //Removed: System.Data.Entity.Database.SetInitializer<MyDbContext>(new DatabaseTestInitializer());
  this.Db = Container.Resolve<MyDbContext>();
  this.Db.Should().NotBeNull();

  //Below: code added
  this.Db.Database.Delete();
  this.Db.Database.Create();
  SeederHelper.Seed(this.Db);
}
like image 79
m4ngl3r Avatar answered Nov 14 '22 23:11

m4ngl3r