0

Controller code:

public ActionResult Edit(int id)
{
    Users result = null;
    using (MyApplicationContext context = new MyApplicationContext())
    {
        ViewBag.Conditions = context.Conditions.Where(x => x.IsActive).OrderBy(x => x.Name).ToList();
        result = context.Users.FirstOrDefault(x => x.Id == id);
    }
        return View("Manage", result);
}

In the view, Manage.cshtml, I have the following code.

@using MyApplicationContext.Models
@model MyApplication.Models.Users

@{
    ViewBag.Title = "Manage";
    List<MyApplication.Models.Condition> conditionList = ViewBag.Conditions;

    foreach (var condition in conditions)
    {
        bool isChecked = Model.Conditions.Any(x => x.Id == condition.Id) ? true : false;
    }

The code is failing on the assignment to isChecked in the foreach loop, but in the editor, Model description is 'Gets the Model property of the associated ViewDataDictionary object.

I don't understand how this is tied to the ObjectContext object. When I remove it, the code which references model (lowercase from @model) is successful.

Thank you,

  • This is happening because you're returning the `result` from an `IQueryable` (your `context.User.FirstOrDefault(...)`), and trying to access property the `result` in your view, when your `context` has already been disposed from your `using` statement. I would suggest looking into "Lazy Loading" with EF, and possibly using your `context` as a field, and disposing it when the controller is disposed of. – Geoff James Jun 24 '16 at 14:38
  • Possible duplicate of [How to solve the error The ObjectContext instance has been disposed and can no longer be used for operations that require a connection](http://stackoverflow.com/questions/18398356/how-to-solve-the-error-the-objectcontext-instance-has-been-disposed-and-can-no-l) – Geoff James Jun 24 '16 at 14:42
  • 1
    Minor nitpick, but convention is typically to match name pluralization to the type of object it is. From your code, `@model MyApplication.Models.Users`, it appears that this should be a collection of users, not a single entity. Most people would expect something called `Users` to be an `IEnumerable`. – Leniency Jun 24 '16 at 18:23

2 Answers2

4

The core cause is that User.Conditions is a lazy-loaded navigation, and your datacontext (and underlying connection) has already been closed in the view.

The quick way to solve this is to ensure Conditions are loaded with the user.

// Include this namespace:
using System.Data.Entity;

Then change the result query:

result = context.Users
    .Include(u => u.Conditions) // <-- Instruct the query to also load Conditions.
    .FirstOrDefault(x => x.Id == id);

Your view can remain the same then.

Leniency
  • 4,984
  • 28
  • 36
0

You have passed in a model of type 'Users' which I assume has a navigation property in it called Conditions. Navigation properties will query the database.

It looks like you mean to write conditionList.Any(x => x.Id == condition.Id) ? true : false; instead of Model.Conditions as you have already flattened a list of conditions. (Using ToList() will query the database at that point and avoid this issue)

If you do need the navigation property instead, you may consider also flattening this like result.Conditions.ToList() and using this instead of the Model.Conditions property.

Milney
  • 6,253
  • 2
  • 19
  • 33
  • This doesn't necessarily fix the OP's problem. The problem is that the `context` was disposed of by the time the data had got to the view, therefore when the navigation property getter is called it's already been disposed of and can no longer query that property :) – Geoff James Jun 24 '16 at 14:40
  • I believe that using conditionList instead of Model.Conditions will indeed fix the issue, but you are right the using comment is incorrect, i will edit answer – Milney Jun 24 '16 at 14:46
  • I still disagree that this will fix the issue entirely. *Just* performing a `.ToList()` to flatten the object doesn't necessarily mean that the navigation properties are there. Chances are that if lazy loading is turned on (which is is by default), the navigation properties will end up being `null`. I suggest the OP looks into "Eager Loading" in order to use your solution. – Geoff James Jun 24 '16 at 14:57