-1

There were many related questions, but none solved my matter. My purpose here is generating a pdf using Razor PDF. So I have a controller action, which contains;

var pdf = new PdfResult(null, "myView");
ViewBag.VrList = MyDbQuery.GetExpiredVL(DateTime.Today);
return pdf;

MyDbQuery is in a different solution which I'm using. And there I have this method:

public static List<VLEntity> GetExpiredVL(DateTime ReportDate)
{
    using (MyDbContext db = new MyDbContext())
    {
        return db.VLEntity.Where(vl => vl.ValidTo.Month == ReportDate.Month && vl.ValidTo.Year == ReportDate.Year).ToList();
    }
}

My view looks like:

@foreach (var vrRow in ViewBag.VrList)
{
    @vrRow.VEntity.VssId
}

When I debug, I get:

System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

In similar questions i have found here says to use using statement. But you can see here I have already used that. I'm very new to ASP.NET and C# altogether and I'll be grateful if you can come up with a solution for this.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
guitarlass
  • 1,587
  • 7
  • 21
  • 45
  • The entities in your list come from the MyDbContext which you Dispose as soon as the list is returned. You want to use something like an IoC container which has per-request lifetime semantics. Alternatively turn off lazy loading or Include the related entities you need. – ta.speot.is Jul 26 '15 at 04:00
  • @ta.speot.is but there is a `ToList()` call that should fetch the results from `DbContext` into memory. Do you think lazy loading is still a problem? – Nikolai Samteladze Jul 26 '15 at 04:03
  • What line the exception is thrown at? How do you use `VrList`? If you call any `Lazy` properties on it that you will need `DbContext` to fetch this data somehow. – Nikolai Samteladze Jul 26 '15 at 04:04
  • You code looks fine. When you step through the code are you sure that line is throwing the exception? –  Jul 26 '15 at 04:15
  • 1
    Based on your edit - `@vrRow.VEntity.VssId` suggests `VLEntity` contains a complex object named `VEntity` - is your query correctly loading that object as well? –  Jul 26 '15 at 04:19
  • @StephenMuecke hey! i added `.Include(vl => vl.VEntity)` to my query. Now it works! Oh! thank you! But what i don't understand is, I have called `MyDbQuery` class methods before and never uncounted a similar error. Any Idea why this now? – guitarlass Jul 26 '15 at 04:26
  • @guitarlass, Impossible to say without seeing the other methods. –  Jul 26 '15 at 04:56

1 Answers1

2

In this code:

@foreach (var vrRow in ViewBag.VrList)
{
    @vrRow.VEntity.VssId
}

You're accessing the navigation property VEntity. If you don't disable lazy loading (which is enabled by default), this property isn't loaded from the database when querying, but only when accessing the property (through proxy generation).

In your data access method you do db.VLEntity.[..].ToList(), but that only materializes the VLEntitys returned from the query - not their navigation properties.

Because of the disconnected scenario (the action method in the controller runs first, then hands its data off to the view), the context is not accessible anymore where you access the navigation property.

For this, you need to explicitly load the navigation property (as you claim you did):

return db.VLEntity
         .Include(v => v.VEntity)
         .Where([..])
         .ToList();

Now when the view accesses the VEntity properties of the list are also materialized, so your view doesn't have to access the database anymore.

You also say it worked before, but then you probably just didn't access any navigation properties.

Related: Best practises in MVC for not disposing the object context?, How to solve the error The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

Alternatives would be to keep the DbContext around longer (which you shouldn't want) and introducing a ViewModel that you map to in the controller.

Community
  • 1
  • 1
CodeCaster
  • 147,647
  • 23
  • 218
  • 272