ComeIn ComeIn - 1 month ago 5
C# Question

EF6 The operation cannot be completed because the DbContext has been disposed

I know there are a bunch of these error messages in SO because I've read them all, sadly to no avail.

I have a WebApi controller that is getting a set of 'Persons' via EF6 from a SQL Server DB. Very simple example

Things I've tried so far, with no success:
- Disabling proxy generation
- Disabling lazy loading
- Adding Includes to get child refs with both linq and string parameters.
- Replacing the using with try/finally -> dispose of DbContext.
- Remove "application/xml" from supported media types via WebApiConfig
- Ensured circular dependencies are attributed with [IgnoreDataMember]
- ... More I cannot remember :)

Here is the PersonController Get method:

public IEnumerable<Person> Get()
{
try
{
IEnumerable<Person> persons = null;
using (PersonContext entities = new PersonContext())
{
entities.Configuration.ProxyCreationEnabled = false;
entities.Configuration.LazyLoadingEnabled = false;
persons = entities.Persons.Take(5);
}
return persons;
}
catch(Exception ex)
{
...
}
}


Now no exception is thrown at ANY point in the controller. The exception is however displayed in the browser:

"<Error><Message>An error has occurred.<\Message>
<ExceptionMessage>The 'ObjectContent`1' type failed to serialize the response body for content type 'application\/json; charset=utf-8'.
<\ExceptionMessage>
<ExceptionType>System.InvalidOperationException<\ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.<\/Message>
<ExceptionMessage>**The operation cannot be completed because the DbContext has been disposed.**<\/ExceptionMessage>
<ExceptionType>System.InvalidOperationException<\/ExceptionType>
<StackTrace> at
System.Data.Entity.Internal.LazyInternalContext.InitializeContext()


The error tells me that something else is trying to read the context after the using clause has popped but I'm at a loss to know what that could be? As you can see I copy the enumerated data from the context into the local list before returning that. Got me stuffed!

Any suggestions appreciated.

Answer

The line

persons = entities.Persons.Take(5);

is a definition of how to retrieve data, but the data itself is not yet retrieved at that point ('delayed execution'). The line is located inside the using(){} construct, so right after that the DbContext is disposed. A while later the View needs the data, the DbContext is consulted, but it is closed already.

Solution:
Retrieve all data before closing the DbContext. This is frequently done using ToArray() or ToList(), whichever suits you best.

So the line should be e.g.:

persons = entities.Persons.Take(5).ToArray();
Comments