简体   繁体   中英

Error: DbContext has been disposed

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

I have a problem with returning JsonResult When I run this code code I get the error

"The operation cannot be completed because the DbContext has been disposed."

I tried adding .ToList() at the end of the line 3, as was suggested, but then I got the error

"A circular reference was detected while serializing an object of type System.Data.Entity.DynamicProxies."

It's not very obvious, but the built-in Json method only does the serialization after the JTask method has finished executing. By that time, of course, the context has been disposed, resulting in the original error you are describing.

If you have an ICollection<TodoItem> property inside your Todo class, each of those will have a ToDo property which is a reference back to the parent. And each of those ToDo properties will also have ICollection<TodoItem> children, which has a reference back to the parent again, and so on and so forth. This can potentially loop for infinity, and when the serializer tries to serialize the object, it gives up with a circular reference error.

One way to solve both of these problems at the same time is by using viewmodels. A viewmodel is an intermediate class that holds only a subset of the properties that a model class has. The typical flow is for the model class to get converted to a viewmodel first, then it would be the viewmodel that gets serialized as 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);

I wrote a blog post about the advantages of using viewmodels. You can check it out here if you're interested: Why Use ViewModels

Because Linq is Lazy by the time the JSON tries to get the data out of a (and only then actually goes to db ) the db has already been disposed - when leaving the scope of the 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);
    }
}
var a = db.ToDos.Where(todo => todo.UserId == id).ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM