MVC 3 - ObjectContext 实例已被释放,不能再用于需要连接的操作

发布于 2024-11-16 13:19:54 字数 1362 浏览 6 评论 0原文

一般来说,我对 C# 和 MVC 非常陌生,我一直在创建自己的小博客网站作为测试项目。尽管到目前为止大多数事情都正常,但我在从 LINQ 查询中选择多个列时遇到了问题。只是在偶然发现 SO 上的一个问题之后,我才意识到我可以使用生成的实体类作为强类型模型来处理这个问题。我需要这个,因为我一直在创建数据库层(这也是我以前没有使用过的东西)并且尝试通过该层传递匿名类型不起作用。我明白为什么会出现这种情况,所以我很满意我正朝着正确的方向前进。

然而,这种做法似乎又给我带来了另一个问题。我尝试了一个简单的测试,从“类别”表中检索 2 列:“类别 ID”和“名称”。我最初尝试了以下操作:

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 is Dispose 错误。阅读这个问题后,我尝试将 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 is Dispose 错误。所以现在我不明白为什么我会收到错误。我什至尝试完全删除 using 指令,但这给了我一个不同的错误:

“实体或复杂类型‘MyProjectModel.Category’无法在 LINQ to Entities 查询中构造。”

如果有帮助,这里是我的观点的相关代码:

@model IEnumerable<MyProject.Models.Category>

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

有人愿意告诉我我缺少什么吗?

谢谢。

I'm very new to C# and MVC in general and I've been creating my own little blog site as a test project. Although most things are working up to this point, I have had problems selecting multiple columns from LINQ queries. It was only after stumbling on a question on SO that I realised I could use the generated entities classes as strongly-typed models to handle this. I've needed this as I've been creating a database layer (which is also something I've not used before) and trying to pass anonymous types through that layer didn't work. I understand why that was the case, so I'm satisfied that I'm heading in the right direction.

However, this approach seems to have given me another problem. I've tried a simple test to retrieve 2 columns from my Categories table: CategoryID and Name. I initially tried the following:

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

    return View(model);
}

This gave me the ObjectContext is disposed error when trying to iterate over the model in the view. After reading this question, I tried moving the return statement outside of the using block and calling AsEnumerable() on the model like so:

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());

However, this is still giving me the same ObjectContext is disposed error when I try to iterate over the model in the view. So now I don't understand why I'm getting the error. I've even tried removing the using directive completely but that gives me a different error:

"The entity or complex type 'MyProjectModel.Category' cannot be constructed in a LINQ to Entities query."

If it helps, here's the relevant code for my view:

@model IEnumerable<MyProject.Models.Category>

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

Would someone be kind enough to enlighten me as to what I'm missing?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌梦深 2024-11-23 13:19:54

在控制器中急于并在处理之前调用 .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
}

现在,虽然这可以解决您的特定问题,但开发人员或依赖注入框架通常会在 BeginRequest 事件中实例化 DbContext ,将其存储在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>
}

Be eager in the controller and call .ToList() before disposing in order to schedule the execution of the query immediately before you have left the using block (as after that it is too late, the context is gone):

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
}

Now, while this will solve your particular problem, what developers or dependency injection frameworks usually do is to instantiate the DbContext inside the BeginRequest event, store it inside the HttpContext.Items so that it is available throughout the execution of the entire request and inside the EndRequest method, retrieve it from HttpContext and dispose it.


UPDATE:

Also it is a good practice to use a view model containing only the properties you would like to use in this particular view:

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

and then inside your action:

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());
    }
}

and in the view:

@model IEnumerable<MyProject.Models.CategoryViewModel>

@foreach (var category in Model)
{
    <p>
        Id: @category.Id 
        Name: @category.Name
    </p>
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文