0

Again I have problem with my project. I have two models created with EF 5 DBContext Generator:

First:

    public int ID_AN { get; set; }
    public string TITLE_OR { get; set; }
    public string TITLE_EN { get; set; }

    public virtual ICollection<GENRES> GENRES { get; set; }

Second:

    public int ID_GE { get; set; }
    public string GENRE { get; set; }

    public virtual ICollection<ANIME> ANIME { get; set; }

After that I created controller:

    public ActionResult Details(int id)
    {
        using (var db = new MainDatabaseEntities())
        {
            return View(db.ANIME.Find(id););             
        }
    }

And View:

@model AnimeWeb.Models.ANIME

@{
ViewBag.Title = "Details";
}

<h2>Details</h2>

<fieldset>
<legend>ANIME</legend>

<div class="display-label">
     @Html.DisplayNameFor(model => model.TITLE_OR)
</div>
<div class="display-field">
    @Html.DisplayFor(model => model.TITLE_OR)
</div>

<div class="display-label">
     @Html.DisplayNameFor(model => model.TITLE_EN)
</div>
<div class="display-field">
    @Html.DisplayFor(model => model.TITLE_EN)
</div>

</fieldset>

To this point everything works fine, but I would like to display all Genres of selected anime. When I try to add

<div>
    @Html.DisplayFor(model => model.GENRES)
</div>

I get an error: "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."

I'm new to MVC so I would be very gratefull if someone could explain to me how to make it possible to work.

Placek
  • 699
  • 2
  • 7
  • 10

3 Answers3

1

This is an Entity Framework issue actually. Once you leave your Controller you are too late to be querying the database. Entity Framework is lazy loading (aka on demand) the Genres. To fix this you should change your query to explicitly load the Genres when retrieving the Anime object.

Update: Never told you how to do that. There are many ways to explicitly or eager load your Genres. The best resource for that would be to read the MSDN page on Loading Related Entities. One way would be to add code similiar to the following in your controller (I think this works with how you have it setup).

public ActionResult Details(int id)
{
    using (var db = new MainDatabaseEntities())
    {
        var anime = db.ANIME.Find(id);
        db.Entry(anime).Collection(a => a.GENRES).Load();
        return View(anime);             
    }
}
scottheckel
  • 9,106
  • 1
  • 35
  • 47
1

you can use "include" extended method to load GENRES,like this:

db.ANIME.Include("GENRES").Find(id)

if you want to use @Html.DisplayFor(model => model.GENRES) to show all of the generes, you can do it with DisplayTemplates,check this ASP.NET MVC display and editor templates.

shimron
  • 596
  • 6
  • 19
  • When I try this way I get an error that System.Linq.IQuerable does not contain a definition for 'Find'. – Placek Nov 14 '13 at 09:07
  • @user2984825 sorry, it's a mistake. try this: db.ANIME.Include("GENRES").FirstOrDefault(t=>t.Id=id); – shimron Nov 14 '13 at 09:19
  • Yeah I thought so, but then again I get the same error like in first post.When I try add Count after GENRES it displays me number 4 (which is good cause there are 4 genres to this anime) so I think Controller is fine but I'm making mistake in view. I'm trying @Html.DisplayFor(model => model.GENRES) but I think I can't just display whole ICollection. I think it should be something like @Html.DisplayFor(model => model.GENRES.GENRE) but GENRE part isn't visible... Any ideas? – Placek Nov 14 '13 at 09:31
  • @user2984825 I had answered your second question in my first reply. you can do it with displayTemplates, see here[http://www.growingwiththeweb.com/2012/12/aspnet-mvc-display-and-editor-templates.html#.UoQ9RvlTSnd] – shimron Nov 14 '13 at 09:40
  • It works. Thank you very much for help, and sorry for being annoying ^^ – Placek Nov 14 '13 at 10:19
0

Consider initializing the context when the controller is initialized, and disposing of it in the controller's dispose method.

This is the pattern (incidentally) that is used by the templates in visual studio.

public class DemoController : Controller
{
    private MainDatabaseEntities db = new MainDatabaseEntities();

    public ActionResult Details(int id)
    {
        return View(db.ANIME.Find(id));
    }

    protected override void Dispose(bool disposing)
    {
        this.db.Dispose();
        base.Dispose(disposing);
    }
}
Martin Booth
  • 8,485
  • 31
  • 31
  • If your pc is slow enough you think this works. I figured it out the hard way. This will not help, because the Disposal of the controller is not dependent on whether the view has been rendered or not. – Silvermind Nov 13 '13 at 23:08
  • Are you sure? http://stackoverflow.com/questions/1401327/entity-framework-how-should-i-instance-my-entities-object also suggests the context will not be disposed until after the view has been rendered if done this way. I say this because there are some helpers which require non-disposed context to work (i.e. ToList is not an option). The WebGrid is one example – Martin Booth Nov 13 '13 at 23:27
  • I am sure about my situation ;) Sometimes switching from `Debug` to `Release` mode gave me the `ObjectDisposedException` while debugging. Could you give me a link to an example of the webgrid using a db context like that?. – Silvermind Nov 14 '13 at 00:21