处理后访问DataContext

时间:2010-12-01 20:08:57

标签: c# linq linq-to-sql datacontext

我正在使用ASP.NET 4.0。

我有以下代码返回错误“无法访问已处置的对象。 对象名:'Dispose后访问的DataContext。'。“

 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。任何人都可以解释为什么第二种方法会起作用而不是第一种方法吗?

感谢。

3 个答案:

答案 0 :(得分:16)

第一个不起作用,因为当方法返回时,using块中实例化的数据上下文被释放。但是,返回的IEnumerable<BatchHeader>被懒惰地评估,并且需要此数据上下文才能生成以枚举其结果。

你可以这样做:

 public IEnumerable<BatchHeader> GetHeaders() {
     using(NSFChecksDataContext context = DataContext) {         
         foreach(var header in context.BatchHeaders) {
             yield return header;
         }
     }
 }

第二个块起作用,因为在处理数据上下文之前,查询结果被枚举并存储在内存中。在那之后,不再需要数据上下文。但是,使用像第二个块一样的代码时要小心;如果BatchHeaders表很大,你只需将它全部存入内存。

现在,这是我的答案中最严重的部分:我绝对不能忍受查看实例化数据上下文的查询。我想知道并控制何时使用我的数据上下文。

答案 1 :(得分:1)

我猜你的上下文中的IEnumerable正在使用延迟执行,所以除非你强制它使用ToList进行枚举,否则在你使用这些值之前不会这样做,在这种情况下,这些值在using块之外,所以对象将被处置。

答案 2 :(得分:-1)

return headers.AsEnumerable(); 

应该可以工作,因为默认情况下,linq查询返回一个IQueryable对象,这意味着在使用foreach,ToArray,ToList或AsEnumerable进行枚举之前,不会从db获取数据。当Asp.Net尝试访问IQueryable并使用foreach获取数据时,连接已经关闭。