web-dev-qa-db-fra.com

L'opération ne peut pas être terminée car le DbContext a été supprimé à l'aide de MVC 4

Je sais que cette question est posée tant de fois. J'ai lu et mis en œuvre toutes les solutions mais je n'ai pas réussi. J'obtiens cette erreur lorsque je récupère des données de la base de données à l'aide d'EF et que je me lie au modèle après avoir utilisé ce modèle sur View.

Mon code de contrôleur est

using System.Linq;
using System.Web.Mvc;
using JsonRenderingMvcApplication.Models;

namespace JsonRenderingMvcApplication.Controllers
{
    public class PublisherController : Controller
    {
        public ActionResult Index()
        {
            PublisherModel model = new PublisherModel();
            using (DAL.DevelopmentEntities context = new DAL.DevelopmentEntities())
            {               
                model.PublisherList = context.Publishers.Select(x =>
                                        new SelectListItem()
                                        {
                                            Text = x.Name,
                                            Value = x.Id.ToString()
                                        }); ;
                           }
            return View(model);
        }

    }
}

Mon code d'affichage est

@model JsonRenderingMvcApplication.Models.PublisherModel

@{
    ViewBag.Title = "Index";
}
<div>
    @Html.DisplayFor(model=>model.Id)
    @Html.DropDownListFor(model => model.Id, Model.PublisherList);
</div>
<div id="booksDiv">

</div>

Mon code de modèle est

using System.Collections.Generic;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;

namespace JsonRenderingMvcApplication.Models
{
    public class PublisherModel
    {
        public PublisherModel()
        {
            PublisherList = new List<SelectListItem>();
        }

        [Display(Name="Publisher")]
        public int Id { get; set; }
        public IEnumerable<SelectListItem> PublisherList { get; set; }
    }
}

Mon code d'entité est

namespace JsonRenderingMvcApplication.DAL
{
    using System;
    using System.Collections.Generic;

    public partial class Publisher
    {
        public Publisher()
        {
            this.BOOKs = new HashSet<BOOK>();
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public string Year { get; set; }

        public virtual ICollection<BOOK> BOOKs { get; set; }
    }
}     

Oui, cette entité a une propriété de navigation, mais je ne veux pas les données de cette entité, donc je ne veux pas l'inclure.

Merci

20
Sandeep Shekhawat

Le problème que vous rencontrez est dû à l'exécution différée de LINQ. C'est un piège pour les développeurs qui n'ont pas encore compris comment LINQ fonctionne sous le capot. J'ai un excellent article de blog à ce sujet, mais le concept de base est que vous devez forcer une énumération sur la collection pour que le code LINQ s'exécute immédiatement au lieu de plus tard. Cela signifie changer cela:

model.PublisherList = context.Publishers.Select(x =>
    new SelectListItem()
    {
        Text = x.Name,
        Value = x.Id.ToString()
    });

pour ça:

model.PublisherList = context.Publishers.Select(x =>
    new SelectListItem()
    {
        Text = x.Name,
        Value = x.Id.ToString()
    }).ToList();

Notez la .ToList() qui force l'énumération.

Votre requête LINQ est différée ce qui signifie qu'elle n'est pas exécutée sur votre contrôleur mais à la place par la suite, probablement à votre avis où vous bouclez sur la collection (ce qui force l'énumération et exécute donc LINQ). Étant donné que vous utilisez l'instruction using pour supprimer votre contexte de base de données (ce qui est bien sûr une bonne pratique), le contexte est supprimé avant d'atteindre la vue, qui exécute le code par rapport au contexte supprimé. Forcer l'énumération dans l'instruction using exécutera le code à ce moment, au lieu de plus tard lorsque le contexte sera supprimé, et évitera ce problème.

60
Haney