簡體   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