0

所以我有 2 张桌子CommentsStudents. 每条评论都有一个学生: Comment.StudentId

我正在使用 POCO 生成的类,当我进行如下查询时,它似乎给了我评论类中的整个 Student 对象:

var query =
    from comment in context.Comments
    where comment.StudentId == properId
    orderby comment.Created
    select comment;

所以我可以像这样访问学生的财产comment.Student.Name

但是,当我复制结果(query.ToList()以在方法外部使用时,它给了我一个错误,说 ObjectContext 实例已被处置。

如何从对象中包含的对象中检索数据?

4

3 回答 3

2

在 .ToList() 之前添加 .Include("Student")

于 2012-11-15T02:29:27.910 回答
1

请记住,Linq 使用IEnumerable,它会延迟查询的执行,直到您尝试迭代结果(就像您通过调用一样.ToList())。如果您.ToList()按照您所说的那样调用“方法之外”,那么您很可能正在处理上下文,这意味着查询对象不再可行。

一个快速而肮脏的技巧是确保在处理上下文之前执行一次查询:

var query =
    (from comment in context.Comments
    where comment.StudentId == properId
    orderby comment.Created
    select comment).ToList();
于 2012-11-15T02:37:08.600 回答
1

在退出包含 dbcontext 的方法之前,您必须调用 .ToList()。这将调用数据库并填写您的 Comment 类。否则,当您尝试在该方法之外“从对象中包含的对象中检索数据”并且尚未加载它们时,您将看到 DbContext 已被释放。这是因为 EF 正在尝试为这些项目再次“加载”或“调用数据库”。当然,由于您现在不在包含上下文的方法之外,因此 EF 无法加载它们。您应该阅读我认为默认打开的 EF 的“延迟加载”功能。

您可能想要创建一个只返回完全加载的 Comment 对象的方法。像这样的东西:

public class YourDbAccessClass {
    public IEnumerable<Comment> GetCommentsByStudentId(int id) {
        using (YourContextClass context = new YourContextClass()) {
            // Eager load Student with the .Include() method.
            var query = from comment in context.Comments.Include("Student")
                        where comment.StudentId == id
                        orderby comment.Created
                        select comment;

            return query.ToList();
        }
    }
}

然后在您的调用代码中:

protected void ...some method on your view or asp page {
    YourDbAccessClass db = new YourDbAccessClass();
    var comments = db.GetCommentsByStudentId(yourIdVariableHere);

    // Now you can loop through those items without dbcontext.
    // Response.Write is probably a bad example, but you probably get the gist here.
    foreach(var comment in comments) {
        Response.Write("<li>" + comment.Student.Name + "</li>");
    }
}
于 2012-11-15T03:20:49.623 回答