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.
Don't dispose DbContext objects. Although the DbContext implements IDisposable , you shouldn't manually dispose it, nor should you wrap it in a using statement. DbContext manages its own lifetime; when your data access request is completed, DbContext will automatically close the database connection for you.
When the controller is being disposed, call dispose on your repository and that should dispose the context. If you are using a service layer and not talking to the repository directly from the controller, then call dispose on the service which will call dispose on repo which will dispose the context.
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With