DataContext Accessed After Dispose

Aaron picture Aaron · Dec 1, 2010 · Viewed 19.7k times · Source

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 context = 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.

Answer

jason picture jason · Dec 1, 2010

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.