Ошибка: DbContext удален

public JsonResult JTask(int id)
{
    using (TestDb db = new TestDb())
    {
        var a = db.ToDos.Where(todo => todo.UserId == id);
        return Json(a, JsonRequestBehavior.AllowGet);
    }
}

У меня проблема с возвратом JsonResult Когда я запускаю этот код кода, я получаю сообщение об ошибке

"Операция не может быть завершена, так как DbContext был утилизирован."

Я пытался добавить .ToList() в конце строки 3, как было предложено, но потом получил ошибку

«Обнаружена циклическая ссылка при сериализации объекта типа System.Data.Entity.DynamicProxies».


person Kioko Key    schedule 01.08.2016    source источник
comment
Вам понадобится ToList в конце, потому что очевидно, что запрос не будет выполняться, пока он не будет оценен. Однако причина, по которой вы получаете циклическую ссылку, я думаю, потому что у вас есть модель, которая имеет свойство навигации к другой модели, у которой есть одна задняя часть. В этом случае вам нужно настроить сериализатор MVC или WebApi JSON, чтобы игнорировать циклы ссылок.   -  person Callum Linington    schedule 01.08.2016
comment
Как у вас дела с сериализацией JSON? Вы настраиваете его в Global.asax или что-то в этом роде?   -  person Callum Linington    schedule 01.08.2016
comment
Вы используете Javascriptserializer или JSON.Net?   -  person Alexander Derck    schedule 01.08.2016
comment
Я понятия не имею, как сделать сериализацию. :(   -  person Kioko Key    schedule 01.08.2016
comment
Библиотека @KiokoKey JSON.NET способна работать с циклическими ссылками, вы должны посмотреть, как ее использовать. Но в идеале у вас не должно быть циклических ссылок при сериализации с использованием DTO.   -  person Alexander Derck    schedule 01.08.2016


Ответы (2)


Это не очень очевидно, но встроенный метод Json выполняет сериализацию только после завершения выполнения метода JTask. К тому времени, конечно, контекст был удален, что привело к исходной ошибке, которую вы описываете.

Если у вас есть свойство ICollection<TodoItem> внутри вашего класса Todo, каждый из них будет иметь свойство ToDo, которое является ссылкой на родителя. И у каждого из этих ToDo свойств также будет ICollection<TodoItem> дочерних элементов, у которых снова есть ссылка на родителя, и так далее и тому подобное. Это потенциально может зацикливаться на бесконечность, и когда сериализатор пытается сериализовать объект, он сдается с ошибкой циклической ссылки.

Один из способов решить обе эти проблемы одновременно — использовать модели представления. Модель представления — это промежуточный класс, который содержит только подмножество свойств, которыми обладает класс модели. Типичный процесс заключается в том, что класс модели сначала преобразуется в модель представления, а затем модель представления сериализуется как json:

var viewModels = new List<TodoViewModel>();

using (TestDb db = new TestDb())
{
    var todoModels = db.ToDos.Where(todo => todo.UserId == id).ToList();

    foreach (var model in todoModels)
    {
        var todoViewModel = new TodoViewModel
        {
            // Populate viewmodel properties here
            Text = model.Text
        };

        viewModels.Add(todoViewModel);
    }
}

return Json(viewModels, JsonRequestBehavior.AllowGet);

Я написал сообщение в блоге о преимуществах использования моделей представления. Вы можете проверить это здесь, если вам интересно: Зачем использовать ViewModels

person OJ Raqueño    schedule 01.08.2016
comment
Спасибо большое!:) Вы мне очень помогли. Я застрял на этом на несколько часов :) - person Kioko Key; 01.08.2016
comment
Без проблем. Добро пожаловать (обратно) в StackOverflow! :) - person OJ Raqueño; 01.08.2016

Поскольку Linq является ленивым, к тому времени, когда JSON пытается получить данные из a (и только затем фактически переходит к db), db уже удален - при выходе из области действия using

public JsonResult JTask(int id)
{
    using (TestDb db = new TestDb())
    {
        var a = db.ToDos.Where(todo => todo.UserId == id).ToList();
        return Json(a, JsonRequestBehavior.AllowGet);
    }
}
person Gilad Green    schedule 01.08.2016
comment
IEnumerables может быть ленивым, но это не весь ответ - person Callum Linington; 01.08.2016
comment
Теперь у меня проблема с Циклическая ссылка была обнаружена при сериализации объекта типа Можете ли вы помочь мне с сериализацией? Я не уверен, как это сделать правильно - person Kioko Key; 01.08.2016