单元测试使用ObjectContext抛出ObjectDisposedException

时间:2013-03-08 02:18:50

标签: entity-framework objectdisposedexception

我有单元测试,我在每个测试方法之前创建和播种SQLCE4数据库。

在测试方法中,如果我有这样的查询:

var maxGroupLevel = repository.Get<GroupLevel>().Max(g => g.Id);

它将抛出以下异常:

System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
Result StackTrace:  
at System.Data.Objects.ObjectContext.EnsureConnection()
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3[TResult](IEnumerable`1 sequence)
   at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
   at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.Max[TSource,TResult](IQueryable`1 source, Expression`1 selector)

但是,如果我在查询中放置一个ToList()调用它可以工作:

var maxGroupLevel = repository.Get<GroupLevel>().ToList().Max(g => g.Id);

怎么回事?

此外,如果我将数据库的创建/种子移动到构造函数而不是TestInitialize方法并在TestInitialize中创建新的上下文,那么一切正常。但是,我不想这样做,因为我希望在每次测试之前数据库处于已知状态。

2 个答案:

答案 0 :(得分:2)

您的第一个代码版本将延迟到第一次查询maxGroupLevel

var maxGroupLevel = repository.Get<GroupLevel>().Max(g => g.Id);

代码的第二个版本在那里运行查询,然后在上面的代码和对maxGroupLevel的第一个引用之间的某处处理上下文。如果没有其他代码的可见性,那么它的帮助就更难了。

答案 1 :(得分:0)

如果不查看其余代码,很难确定确切的问题。但你可能想要 在使用与ObjectDisposedException异常相关的Entity Framework时要了解两件事。

1)在从数据库中提取所有数据之前,不得处理数据上下文。

2)linq语句创建一个IQueryable,直到你枚举它才会执行   (例如,在每个循环中使用它)或将其转换为列表或数组。