繁体   English   中英

使用实体框架获取数据以便可以在对象之间导航的正确方法是什么?

[英]What's the proper way to get data using Entity Framework so you can navigate through objects?

我有一个正在玩的.Net 4.5 MVC 5数据库第一个项目。 有数据访问层(实体框架6),业务逻辑层和MVC层。

如果我在数据层中有一个具有关系的对象:

namespace DataAccess
{
    public class Course
    {
        public int CourseID { get; set; }
        public string Title { get; set; }

        public ICollection<Lecture> Lectures { get; set; }
        public ICollection<Tutor> Tutors { get; set; }
    }
    public class Lecture
    {
        public int LectureID { get; set; }
        public string Title { get; set; }
        public DateTime Date { get; set; }
        public ICollection<Student> Students { get; set; }
    }
    public class Tutor
    {
        public int TutorID { get; set; }
        public string Name { get; set; }
    }
    public class Student
    {
        public int StudentID { get; set; }
        public string Name { get; set; }
    }
}

在我的业务逻辑层中,我有一种获取课程的方法:

namespace BusinessLogic
{
    public static IEnumerable<Course> GetCourses()
    {
        using (var db = new MyEntities())
        {
            return db.Courses.Include("Lectures").Include("Lectures.Students").Include("Tutors").ToList();
        }
    }
}

然后使用我的控制器获取数据,如下所示:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var courses = BusinessLogic.GetCourses();
        return View(courses);
    }
}

为什么这样,当我在Razor视图中查询数据时,如下所示:

var numLectures = courses.Lectures.Count;
var numStudents = courses.Lectures.Students.Count;
var tutorName = courses.Tutors.LastOrDefault().Name;

我收到应用程序错误System.ObjectDisposedException:ObjectContext实例已被处置,不能再用于需要连接的操作

我知道在using语句完成后会断开连接,并且.ToList()将使我可以浏览课程对象,但是如何浏览每门课程中的对象(即讲座,学生,导师等)?

您的导航属性需要声明为virtual

namespace DataAccess
{
    public class Course
    {
        public int CourseID { get; set; }
        public string Title { get; set; }

        public virtual ICollection<Lecture> Lectures { get; set; }
        public virtual ICollection<Tutor> Tutors { get; set; }
    }
    public class Lecture
    {
        public int LectureID { get; set; }
        public string Title { get; set; }
        public DateTime Date { get; set; }
        public virtual ICollection<Student> Students { get; set; }
    }
    ...
}

当这些可延迟加载的属性未标记为virtual ,EF动态代理将无法覆盖它们,并且您将永远无法从一个实体导航到另一个实体。

另一点建议:急于加载时,请使用强类型的.Include

namespace BusinessLogic
{
    public static IEnumerable<Course> GetCourses()
    {
        using (var db = new MyEntities())
        {
            return db.Courses
                .Include(x => x.Lectures.Select(y => y.Students))
                .Include(x => x.Tutors)
                .ToList();
        }
    }
}

我认为问题是因为查询中不包含您在View中调用的一个(或多个)属性。 确保在视图中包含所需的所有导航属性。 尝试使用以下查询:

  using (var db = new MyEntities())
  {
    return db.Courses.db.Courses.Include(c=>c.Lectures.Select(l=>l.Students)).Include(c=>c.Tutors‌​).ToList()
  }

如果您需要添加在View中使用的另一个相对属性,请为该属性添加另一个Include调用。

另一件事,当您需要加载两个级别(例如Lectures.Students )时,不需要为每个级别添加一个Include调用,而您对第二个级别所做的调用就足以包含这两个级别。 可能是这样的:

.Include("Lectures.Students") // as you did it

要么:

.Include(c=>c.Lectures.Select(l=>l.Students))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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