您必须意识到DbSet<Student> 并不代表您的Students 集合,它代表您数据库中的Students 表。这意味着您可以查询Students 的属性序列。
如果需要,您可以查询完整的序列,但这会导致性能问题,如果不是内存问题。
因此,如果您要求Student 数据,您必须牢记您将使用获取的数据的用途:不要选择您已经知道其值的属性,不要选择您知道的项目不打算使用。
一个例子:一个具有Schools和Students的数据库,具有一对多的关系,每个School有零个或多个Students,每个Student恰好参与一个School:
class School
{
public int Id {get; set;}
public string Name {get; set;}
...
// every School has zero or more Students (one-to-many)
public virtual ICollection<Student> Students {get; set;}
}
class Student
{
public int Id {get; set;}
public string Name {get; set;}
...
// Every Student attends exactly one School, using foreign key:
public int SchoolId {get; set;}
public virtual School School {get; set;}
}
在实体框架中,表的列由非虚拟属性表示。虚拟属性表示表之间的关系(一对多,多对多,...)
请勿执行以下操作!
public IEnumerable<School> GetSchoolByLocation(string city)
{
return mySchoolWithItsStudents = dbContext.Schools
.Where(school => school.City == city)
.Include(school => school.Students)
.ToList();
}
为什么不呢?这看起来像是完美的代码,不是吗?
也许您获取的数据比调用者使用的数据多:
var mySchoolId = GetSchoolByLocation("Oxford")
.Where(school => schoolStreet == "Main Street")
.Select(school => school.Id)
.FirstOrDefault();
太浪费了,先把牛津所有的学校都拿来,然后只保留这一个!
此外:您获得了学校及其所有学生,以及您使用的所有学校 ID?
尽量返回IQueryable<...>,让调用者决定如何处理返回的数据。
也许他想做ToList,或Count,或FirstOrDefault。也许他只想要Id 和Name。只要你不知道,就不要替他做决定,只会让你的代码更难复用。
始终使用Select 选择属性,并且只选择您实际计划使用的数据。如果您打算更新包含的数据,请仅使用Include。
var schools = dbContext.Schools.Where(school => ...)
// Keep only the Schools that you actually plan to use:
.Select(school => new
{
// only select the properties that you plan to use
Id = school.Id,
Name = school.Name,
...
// Only the Students you plan to use:
Students = school.Students.Where(student => ...)
.Select(student => new
{
// Again, only the properties you plan to use
Id = student.Id,
Name = student.Name,
// no need for the foreign key: you already know the value
// SchoolId = student.SchoolId,
}),
});
最后,如果您想访问所有Students 以显示它们,但又不想一次获取所有百万学生,请考虑按页面获取它们。记住最后抓取页面的最后一项的主键,使用`.Where(item => item.Id > lastFetchedPrimaryKey).Take(pageSize)获取下一页,直到没有更多页面为止。
这样,您可能会要求 50 个学生,而您只会显示其中的 25 个,但至少您不会在内存中拥有所有百万学生。获取下一页相当快,因为主键上已经有一个索引,并且获取的项目已经按主键排序。