Почему "Dispose" работает, а не"using(var db = new DataContext ())"?
Я создаю форум, который состоит из разделов, которые состоят из сообщений.
когда я пытаюсь реализовать представление темы В моем контроллере с помощью:
public ActionResult Topic(int id) //Topic Id
{
using (var db = new DataContext())
{
var topic = db.Topics.Include("Messages").Include("Messages.CreatedBy").Include("CreatedBy").FirstOrDefault(x => x.Id == id);
//include the messages for each topic, and when they were created so that the last message can be displayed on the topic page
return topic != null ? View(topic) : View();
}
}
Я получаю эту ошибку при попытке просмотреть страницу темы:
ObjectDisposedException был необработан кодом пользователя
экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих соединение.
ошибка не кажется специфичной для определенной строки, так как, когда я удаляю оскорбительную строку, та же ошибка появляется ранее.
Я решил это, используя:
DataContext db = new DataContext();
в начале контроллера и:
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
в конце (и с using
out)
хотя это работает, мне любопытно, почему "использование" не работает, и я не очень доволен тем, что соединение открыто по всему контроллеру, и утилизировать его вручную в конце.
4 ответов
У любого из ваших объектов включена ленивая загрузка? Похоже, что в ваших представлениях выполняются запросы, но вы избавляетесь от своего контекста, прежде чем они будут выполнены (следовательно, ошибка говорит, что она уже удалена). Если вы поместите удаление в метод Dispose контроллера, представление будет выполнено до удаления контроллера и контекста.
Я рекомендую установить Glimpse.Mvc5 и мельком.Ef6 в пакеты. После настройки glimpse вы можете видеть каждый запрос это выполняется на Вашей странице. Вы можете быть удивлены, увидев, что выполняется несколько дополнительных запросов, которые вы не намеревались. Вот почему я не рекомендую использовать сущности непосредственно в ваших представлениях.
это происходит потому, что обычно объекты LINQ являются прокси-объектами. Если у вас есть что-то вроде MyEntity.ChildEntities
базовый SQL-запрос не выполняется для извлечения этих объектов до выполнения кода. Если вы обращаетесь к ним в представлении, представление не будет связано до тех пор, пока метод action не вернется, и в этот момент DbContext уже будет удален.
жизненный цикл выглядит примерно так:
- вызовите метод действия
- внешний запрос для выборки the
topic
выполняется, но любые дополнительные методы доступа в представлении, которые запускают больше SQL-запросов, еще не выполнены. - теперь мы оставили метод действия, так что
using
просто утилизировал ваш DbContext. - платформа MVC привязывает модель к представлению, которое фактически запускает выполнение любых оставшихся запросов и завершается ошибкой, так как DbContext удален.
- жизненный цикл запроса заканчивается, поэтому контроллер удален.
Это была проблема с отложенной загрузки, так что спасибо за точку в правильном направлении @освобождающий лук
когда я использовал '.Включить " для загрузки каждого виртуального свойства темы, он работал нормально:
var topic = db.Topics.Include("Messages").Include("Messages.CreatedBy").Include("CreatedBy").Include("Forum").Include("DeletedBy").FirstOrDefault(x => x.Id == id);
Я думаю, было бы невозможно для кого-либо узнать, какие свойства я объявил виртуальными без меня, извините!
кстати, он работал раньше, когда я проверял свойства в режиме отладки, потому что каждое свойство должно быть загружено для меня, чтобы проверить его
вы не можете вернуть представление или что-то внутри, используя контекст, поскольку это вызывает проблему с удалением контекста здесь.
правильный способ использования using
утверждение в вашем случае
public ActionResult Topic(int id) //Topic Id
{
Topic topic = null; // topic is your POCO
using (var db = new DataContext())
{
topic = db.Topics.Include("Messages").Include("Messages.CreatedBy").Include("CreatedBy").FirstOrDefault(x => x.Id == id);
}
return topic != null ? View(topic) : View();
}
также не делайте перенаправление ответа, если вы используете оператор..
смотрите здесь : удаление контекста базы данных с помощью оператора using в MVC