Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 825
ComeIn Avatar asked Apr 25 '16 12:04

ComeIn


People also ask

Does DbContext need to be disposed?

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.

How do I dispose of DbContext in EF core?

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.


1 Answers

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();
like image 196
Peter B Avatar answered Oct 13 '22 23:10

Peter B