在Nhibernate标准中指定关联深度

时间:2013-08-28 18:34:31

标签: nhibernate fluent-nhibernate nhibernate-criteria

好吧,假设我有一个多对多的学生/班级对象。使用以下映射

      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会迫使我明确指出我想要保湿的东西

1 个答案:

答案 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不要返回由左外连接生成的重复学生。