Операция не может быть завершена, поскольку DbContext был удален с использованием MVC 4
Я знаю, что этот вопрос задают так много раз. Я прочитал и реализовал все решения, но не добился успеха. Я получаю эту ошибку, когда я извлекаю данные из базы данных с помощью EF и связывается с моделью после этого, используя эту модель в представлении.
Мой код контроллера
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);
}
}
}
Код My View
@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>
Мой код модели
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; }
}
}
Мой код объекта
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; }
}
}
Да, этот объект имеет свойство навигации, но я не хочу данных этого объекта, поэтому я не хочу включать его.
Спасибо
Ответы
Ответ 1
Проблема, с которой вы столкнулись, связана с отсроченным исполнением LINQ. Это совершенно для разработчиков, которые еще не поняли, как LINQ работает под капотом. У меня есть замечательная статья в блоге, но основная идея заключается в том, что вы должны принудительно перечислять в коллекции, чтобы привести код LINQ немедленно, а не позже. Это означает следующее:
model.PublisherList = context.Publishers.Select(x =>
new SelectListItem()
{
Text = x.Name,
Value = x.Id.ToString()
});
:
model.PublisherList = context.Publishers.Select(x =>
new SelectListItem()
{
Text = x.Name,
Value = x.Id.ToString()
}).ToList();
Обратите внимание на .ToList()
, который заставляет перечисление.
Ваш запрос LINQ отложен означает, что он не запускается на вашем контроллере, а вместо этого, возможно, в вашем представлении, где вы перебираете коллекцию (которая заставляет перечисление и таким образом запускает LINQ), Поскольку вы используете оператор using
, чтобы избавиться от своего контекста БД (что, конечно же, хорошая практика), контекст удаляется, прежде чем вы достигнете представления, которое выполняет код против расположенного контекста. Принуждение перечисления в инструкции using
будет запускать код в это время, а не позже, когда контекст будет удален, и предотвратить эту проблему.