开发者

DataContext Accessed After Dispose

开发者 https://www.devze.com 2023-01-27 16:58 出处:网络
I\'m using ASP.NET 4.0. I\'ve got the following code that returns with an error of \"Cannot access a disposed object.

I'm using ASP.NET 4.0.

I've got the following code that returns with an error of "Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.'."

 public IEnumerable<BatchHeader> GetHeaders()
            {
                using(NSFChecksDataContext context = DataContext)
                {
                    IEnumerable<BatchHeader> headers = (from h in context.BatchHeaders
                                                        select h);                
                    return headers;                            
                }
            }

If I change this to:

public IEnumerable<BatchHeader> GetHeaders()
        {
            using(NSFChecksDataContext con开发者_高级运维text = DataContext)
            {            
                return context.BatchHeaders.ToList();                            
            }
        }

It will work fine. I'm using this method to populate a RadGrid. Can anyone explain why the second method will work but not the first?

Thanks.


The first doesn't work because when the method returns the data context instantiated in the using block is disposed. However, the IEnumerable<BatchHeader> returned is lazily evaluated and needs this data context to be alive to enumerate its results.

You could do something like this:

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

The second block works because the query results are enumerated over and stored in memory before the data context is disposed of. After that happens, the data context isn't needed anymore. However, be careful when using code like your second block; if the BatchHeaders table is large you just pulled it all into memory.

Now, and here is the most serious part of my answer: 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.


I'm guessing the IEnumerable from your context is using deferred execution, so unless you force it to enumerate using ToList it doesn't do so until you use the values, which in this case is outside of the using block so the object will be disposed.


return headers.AsEnumerable(); 

should work, because by default, a linq query returns an IQueryable object, which means that the data is not fetched from db until enumerated using foreach, ToArray, ToList or AsEnumerable. When Asp.Net tried to access the IQueryable and fetch the data using foreach, the connection was already closed.

0

精彩评论

暂无评论...
验证码 换一张
取 消