如果您Id
从表中删除字段,StudentsSubject
然后从模型中删除此表并更新您的模型,EF 将自动将此表转换为两个导航属性Subjects
和Students
forStudent
和Subject
实体。
如果您必须保持 StudentsSubject 表架构不变,您可以使用Include()
方法来获取学生及其科目:
var students = dbContext.Students.Include("StudentsSubject.Subject")
使用“普通”导航属性,您可以编写以下内容:
var students = dbContext.Students.Include("Subjects")
有时您需要组装大图,然后 Include() 和延迟加载会影响性能。这种情况有一个小技巧:
// switch off for performance
DbContext.Configuration.AutodetectChangesEnabled = false;
// load root entities
var roots = dbContext.Parents.Where( root => %root_condition%).ToList();
// load entities one level lower
dbContext.DependentEntities.Where( dependent => dependent.Root%root_condition% && %dependent_condition%).ToList();
// detect changes
dbContext.ChangeTracker.DetectChanges();
// enable changes detection.
DbContext.Configuration.AutodetectChangesEnabled = true;
现在root.Dependents
集合已填充为roots
.
这是连接冗余(包括或连接)和几个数据库请求之间的权衡,以及请求的复杂性增加。
对于连接节点的“包含”数据是重复的,因此包含链可以产生从数据库到客户端的巨大流量。
使用第二种方法,每个级别都需要在 Where() 中过滤所有上层的条件,EF 为第 N 级生成具有 N-1 个连接的查询,但没有冗余的地方。
据我所知,EF 现在可以很好地与 Contains() 一起使用,并且父节点的条件可以替换为Contains()
:
// load root entities
var roots = dbContext.Parents.Where( root => %root_condition%).ToList();
var rootIds = new List<int>( roots.Select( root => root.Id));
// load entities one level lower
dbContext.DependentEntities.Where( dependent => %dependent_condition% && rootIds.Contains( dependent.RootId)).ToList();