MVC 3 - экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих подключения - PullRequest
5 голосов
/ 20 июня 2011

Я очень новичок в C # и MVC в целом, и я создал свой собственный небольшой блог-сайт в качестве тестового проекта. Хотя до этого момента все работало, у меня были проблемы с выбором нескольких столбцов в запросах LINQ. Только после того, как я наткнулся на вопрос о SO, я понял, что могу использовать сгенерированные классы сущностей как строго типизированные модели, чтобы справиться с этим. Мне это нужно, так как я создавал слой базы данных (который я тоже раньше не использовал) и пытался пропустить анонимные типы через этот слой, но это не помогло. Я понимаю, почему это так, поэтому я удовлетворен тем, что иду в правильном направлении.

Однако этот подход, похоже, дал мне еще одну проблему. Я пробовал простой тест для извлечения 2 столбцов из моей таблицы категорий: CategoryID и Name. Я изначально пробовал следующее:

using (MyEntities db = new MyEntities())
{
    var model = from c in db.Categories
                select new Category { CategoryID = c.CategoryID, Name = c.Name };

    return View(model);
}

Это дало мне ошибку ObjectContext при попытке перебрать модель в представлении. Прочитав этот вопрос , я попытался переместить оператор return за пределы блока using и вызвать AsEnumerable () для модели следующим образом:

IEnumerable<Category> model;

using (MyEntities db = new MyEntities())
{
    model = from c in db.Categories
            select new Category { CategoryID = c.CategoryID, Name = c.Name };
}

return View(model.AsEnumerable());

Однако, это все еще дает мне ту же ошибку ObjectContext, когда я пытаюсь перебрать модель в представлении. Так что теперь я не понимаю, почему я получаю ошибку. Я даже пытался полностью удалить директиву using, но это выдает мне другую ошибку:

"Сущность или сложный тип 'MyProjectModel.Category' не могут быть созданы в запросе LINQ to Entities."

Если это поможет, вот соответствующий код для моего взгляда:

@model IEnumerable<MyProject.Models.Category>

@foreach (var category in Model)
{
    <p>@category.Name</p>
}

Будет ли кто-то достаточно любезен, чтобы просветить меня о том, что мне не хватает?

Спасибо.

1 Ответ

12 голосов
/ 20 июня 2011

Будьте нетерпеливы в контроллере и вызовите .ToList() перед удалением, чтобы запланировать выполнение запроса непосредственно перед тем, как вы покинете блок using (поскольку после этого слишком поздно, контекст исчезает):

using (MyEntities db = new MyEntities())
{
    var model = 
        from c in db.Categories
        select new Category 
        { 
            CategoryID = c.CategoryID, 
            Name = c.Name 
        };
    return View(model.ToList()); // <-- .ToList() here
}

Теперь, хотя это и решит вашу конкретную проблему, разработчики или платформы внедрения зависимостей обычно создают экземпляр DbContext внутри события BeginRequest, сохраняют его внутри HttpContext.Items, чтобы ондоступен во время выполнения всего запроса и внутри метода EndRequest, извлеките его из HttpContext и утилизируйте его.


ОБНОВЛЕНИЕ:

Также это хорошая практикаиспользовать модель представления, содержащую только те свойства, которые вы хотели бы использовать в данном конкретном представлении:

public class CategoryViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

, а затем внутри действия:

public ActionResult Index()
{
    using (MyEntities db = new MyEntities())
    {
        var model = 
            from c in db.Categories
            select new CategoryViewModel
            { 
                Id = c.CategoryID, 
                Name = c.Name 
            };
        return View(model.ToList());
    }
}

и в представлении:

@model IEnumerable<MyProject.Models.CategoryViewModel>

@foreach (var category in Model)
{
    <p>
        Id: @category.Id 
        Name: @category.Name
    </p>
}
...