【问题标题】:DataContext Accessed After DisposeDispose 后访问的 DataContext
【发布时间】:2011-05-18 17:37:17
【问题描述】:

我正在使用 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。谁能解释一下为什么第二种方法行得通,但第一种不行?

谢谢。

【问题讨论】:

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


【解决方案1】:

第一个不起作用,因为当方法返回时,using 块中实例化的数据上下文被释放。但是,返回的 IEnumerable&lt;BatchHeader&gt; 是延迟评估的,需要此数据上下文处于活动状态才能枚举其结果。

你可以这样做:

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

第二个块之所以有效,是因为在处理数据上下文之前,查询结果已被枚举并存储在内存中。之后,不再需要数据上下文。但是,在使用像第二个块这样的代码时要小心;如果BatchHeaders 表很大,您只需将其全部拉入内存即可。

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

【讨论】:

  • 杰森,您的回答确实纠正了我的问题。你能否详细说明你说你不能忍受并解释为什么你不能忍受?我想学习好的做法...
  • I absolutely can't stand seeing queries that instantiate data contexts to execute. I want to know and control when my data contexts are being used. -- 为什么?
【解决方案2】:

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

【讨论】:

    【解决方案3】:
    return headers.AsEnumerable(); 
    

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

    【讨论】:

    • 这很危险。您不知道表有多大,这会将其全部拉入内存。
    • @Jason 它比你的回答危险吗?据我所知,他们都将整个表格拉入内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    相关资源
    最近更新 更多