0

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

      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

我想要的是约翰,代数和生物学这来了,但是生物学来自约翰和苏,她反过来给我生物和历史,其中填充了苏和弗兰肯斯坦。你不想得到弗兰肯斯坦(或生物学以外的任何东西)。您也可以在任何时候开始循环骑行。

我如何指定不填充那么深?SetMaxRows 显然不是我想要的,因为它减少了总行数,我只想补充第一级。我特别困惑,因为我认为 LazyLoading 会迫使我准确指定我想要补水的东西

4

1 回答 1

1

延迟加载使您不必指定要补水的内容。这些集合将在您访问它们时“懒惰地”填充。您的上述查询只会获取一行:John。当您访问时john.Classes,NHibernate 将在后台执行另一个查询以获取 John 的类。然后,当您访问该biology.Students属性时,NHibernate 将执行另一个查询来填充该集合......等等。

肯定希望在这种关系上进行延迟加载(顺便说一下,这是默认设置)。如果您关闭延迟加载,那么这将完全按照您所说的要避免 - NHibernate 会知道不允许延迟加载这些集合,因此它会在您加载学生后立即开始加载它们,这可能最终会加载这三个表中的所有数据,并且以一种非常低效的方式与数据库进行大量往返。

如果您知道您想要的只是“John, with Algebra and Biology”,那么您应该将这些行添加到您的查询中:

    .SetFetchMode("Classes", FetchMode.Eager)
    .SetResultTransformer(Transformers.DistinctRootEntity)

告诉 NHibernate使用SetFetchMode左外连接来预填充student.Classes集合。DistintRootEntity告诉 NHibernate 不要返回将由左外连接生成的重复学生。

于 2013-08-30T01:09:52.953 回答