Search code examples
c#entity-frameworkasp.net-mvc-5objectdisposedexception

ObjectDisposedException even though I'm using .Include(), .ToList(), and everything else


My project is C# .NET, MVC 5, EF6. I'm getting an ObjectDisposedException on using an object in a view that has been gotten from the database. I've read probably EVERY similar question, but .Include() does NOT work; I'm thinking the problem doesn't have anything to do with lazy loading.

The controller method:

public ActionResult Browse()
{
    List<QuestionGroup> questionGroupsWithLinks = new List<QuestionGroup>();
    using (CLASSContext context = new CLASSContext())
    {
        questionGroupsWithLinks = context.QuestionGroup.Include(qg => qg.Questions.Select(q => q.Answers))
            .Where(qg => qg.QuestionGroupID == 128).ToList();
        return View("Browse", questionGroupsWithLinks);
    }
}

I've tried having the using statement not wrap around the view, I've tried declaring questionGroupWithLinks in different places, I've tried iterating through questionGroupWithLinks and assigning one of its properties in hopes that that would load it (didn't make any difference, because the problem is only in the view. It's always loaded as long as you're in the controller method), and I've tried other things as well.

The view (simplified):

@model List<CLASSOnlineAssessments.Models.Assessments.QuestionGroup>
<div class="page-copy">
    @if (Model != null)
    {
        foreach (QuestionGroup qg in Model)
        {
            //More code here; but it always fails before this point.
        }
    }
</div>

I've tried using Model.First() to access a question group instead of foreach, but that doesn't make any difference.

Let me know if I can clarify anything or post more information.


Solution

  • Have you tried this?

    public ActionResult Browse()
    {
        CLASSContext context = new CLASSContext();
        List<QuestionGroup> questionGroupsWithLinks = context.QuestionGroup
            .Include(qg => qg.Questions.Select(q => q.Answers))
            .Where(qg => qg.QuestionGroupID == 128).ToList();
        return View("Browse", questionGroupsWithLinks);
    }
    

    If this does not cause the error, then it does smell like an issue with lazy loading, and you should post your source for the QuestionGroup entity as well as the Question and Answer entities so that we can provide more help.

    In all likelihood you have some other virtual navigation or collection property on QuestionGroup, Question, or Answer that EF is trying to load while rendering your view. However since you disposed of the context, EF cannot lazy load it, and throws the exception.

    BTW, don't use the above in production. You should always have the DbContext disposed of at the end of the request somehow. In reality, you should be doing something more like this:

    public ActionResult Browse()
    {
        using (CLASSContext context = new CLASSContext())
        {
            List<QuestionGroupViewModel> questionGroupsWithLinks = context.QuestionGroup
                .Include(qg => qg.Questions.Select(q => q.Answers))
                .Where(qg => qg.QuestionGroupID == 128)
                .Select(x => new QuestionGroupViewModel
                 {
                     Id = x.Id,
                     // ...etc.
                 })
                .ToList();
            return View("Browse", questionGroupsWithLinks);
        }
    }
    

    With the above, you completely transfer all of the data from the entity attached to the context to a ViewModel Data Transfer Object. If the ObjectDisposedException error really is coming from EF, then the above would ensure that nothing further would happen with the DbContext after it gets disposed.