在连续查询中由EnsureConnection()抛出ObjectContext(没有使用导航属性,没有使用())

Ere*_*ith 5 c# linq entity-framework ef-code-first

不知何故,EF在两个查询之间处理ObjectContext,没有任何进一步的通知,但显然不是随机的,也不是由于超时.

我添加了使用,所以示例是自包含的,但它与整个应用程序中使用的DbContext相同.

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"
}
Run Code Online (Sandbox Code Playgroud)

通知db尚未使用,因此这是不可能的.错误也发生在.First().Where().Single/First().

反转这两个请求不起作用:

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"
}
Run Code Online (Sandbox Code Playgroud)

我也不使用Employee的任何导航属性,这不能解决问题:

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
}
Run Code Online (Sandbox Code Playgroud)

我所注意到的是这个问题在WebSite项目中没有发生,只在UnitTests项目中发生.我为这两个设置了相同的connectionString(除了数据库名称),但也没有做任何事情.

更糟糕的是:

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
}
Run Code Online (Sandbox Code Playgroud)

超时设置为20000并MultipleActiveResultSets设置为true.

目前我发现的唯一解决方法是.ToList()在尝试之前调用整个DbSet .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
}
Run Code Online (Sandbox Code Playgroud)

但这是不可接受的,因为操作频繁,我希望DbSet非常大,所以这将花费大量时间.

小智 1

好吧,正如我们(经过 Eregrith 的更多努力)发现的那样,是 EF 在将其发送到测试初始化​​程序之前对上下文进行了操作,因此它意外地运行;通过实现基本的创建/种子/删除而不是初始化程序,异常消失了。(在我看来,仍然需要更详细地调查那里实际发生的情况=])

测试初始化​​程序的调用如下:

System.Data.Entity.Database.SetInitializer<MyDbContext>(new DatabaseTestInitializer());
Run Code Online (Sandbox Code Playgroud)

数据库测试初始化​​器:

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

删除对 SetInitializer<> 的调用解决了问题。

在基类 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);
}
Run Code Online (Sandbox Code Playgroud)