我使用的是ASP.NET 4.0。
下面的代码返回错误:"Cannot access a disposed object. Object name:'DataContext accessed Dispose.‘“
public IEnumerable<BatchHeader> GetHeaders()
{
using(NSFChecksDataContext context = DataContext)
{
IEnumerable<BatchHeader> headers = (from h in context.BatchHeaders
select h);
return headers;
}
}如果我将其更改为:
public IEnumerable<BatchHeader> GetHeaders()
{
using(NSFChecksDataContext context = DataContext)
{
return context.BatchHeaders.ToList();
}
}它会工作得很好。我使用这个方法来填充一个RadGrid。有没有人能解释为什么第二种方法有效,而第一种方法不行?
谢谢。
发布于 2010-12-02 04:12:54
第一种方法不起作用,因为当该方法返回时,在using块中实例化的数据上下文将被释放。但是,返回的IEnumerable<BatchHeader>是延迟计算的,并且需要此数据上下文处于活动状态才能枚举其结果。
你可以这样做:
public IEnumerable<BatchHeader> GetHeaders() {
using(NSFChecksDataContext context = DataContext) {
foreach(var header in context.BatchHeaders) {
yield return header;
}
}
}第二个块之所以起作用,是因为在数据上下文被处理之前,查询结果被枚举并存储在内存中。在此之后,不再需要数据上下文。但是,在使用像第二个代码块这样的代码时要小心;如果BatchHeaders表很大,则只需将其全部放入内存。
现在,这是我答案中最严肃的部分:我绝对不能忍受看到实例化要执行的数据上下文的查询。我想知道并控制何时使用我的数据上下文。
发布于 2010-12-02 04:13:42
我猜想上下文中的IEnumerable正在使用延迟执行,所以除非使用ToList强制它枚举,否则在使用值之前它不会这样做,在本例中,值在using块之外,因此对象将被释放。
发布于 2010-12-02 04:11:35
return headers.AsEnumerable(); 应该可以工作,因为在默认情况下,linq查询返回一个IQueryable对象,这意味着在使用foreach、ToArray、ToList或AsEnumerable枚举之前,不会从db中提取数据。当Asp.Net尝试访问IQueryable并使用foreach获取数据时,连接已经关闭。
https://stackoverflow.com/questions/4328594
复制相似问题