好吧,假设我有一个多对多的学生/班级对象。使用以下映射
HasManyToMany(m => m.Classes)
.Table("StudentClasses")
.LazyLoad()
.Cascade.None();
和查询:
return _session.CreateCriteria<Student>()
.Add(Restrictions.Eq("Id", studentId))
.SetCacheable(false)
.UniqueResult<Student>();
我的桌子
ID | Student ID | Class StudentId | ClassId
============ =========== ===================
1 | John 1 | Algebra 1 | 1
2 | Sue 2 | Biology 1 | 2
3 | Frank 3 | Speech 2 | 2
4 | Jim 4 | Athletics 2 | 5
5 | Frankenstein 5 | History 5 | 5
我想要的是 John,代数和生物学这就是,但生物学与John和Sue一起来,她反过来让我获得生物和历史,其中包括起诉和弗兰肯斯坦。你不想得到弗兰肯斯坦(或任何超越生物学的东西)。此外,您可以随时开始循环回来。
如何指定不深入填充? SetMaxRows显然不希望我正在寻找,因为它减少了总行数,我只想补充第一级。我特别困惑,因为我认为LazyLoading会迫使我明确指出我想要保湿的东西
答案 0 :(得分:1)
延迟加载允许您不必须指定您想要保湿的内容。在您访问它们时,这些集合将“懒洋洋地”填充。您的上述查询只会获取一行:John。当您访问john.Classes
时,NHibernate将在幕后执行另一个查询以获取John的类。然后,当您访问biology.Students
属性时,NHibernate将执行另一个查询来填充该集合......依此类推。
你肯定想要对这种关系进行延迟加载(顺便说一下,这是默认设置)。如果你关闭延迟加载,那么这就完全可以解决你想要避免的问题 - NHibernate会知道它不允许懒洋洋地加载这些集合,因此一旦你加载学生它就会开始加载它们,这可能最终导致加载这三个表中的所有数据,并且以非常低效的方式进行数据库的大量往返。
如果您知道您想要的只是“John,with Algebra and Biology”,那么您应该将这些行添加到您的查询中:
.SetFetchMode("Classes", FetchMode.Eager)
.SetResultTransformer(Transformers.DistinctRootEntity)
SetFetchMode
告诉NHibernate使用左外连接预先填充student.Classes
集合。 DistintRootEntity
告诉NHibernate不要返回由左外连接生成的重复学生。