1

我有一个模型,其中 aPerson有一个延迟加载的 s 集合Registration。我的 NHibernate 3.3.3 查询JoinQueryOver在该关系中使用以及更多:

var reg = Session.QueryOver<Person>()
    .Where(p => p.ID == pid)
    .JoinQueryOver<Registration>(p => p.Registrations)
    .Where(r => r.IsDropped == false)
    .JoinQueryOver<Slot>(r => r.Slot)
    .JoinQueryOver<Position>(s => s.Position)
    .JoinQueryOver<AcademicTerm>(p => p.Term)
    .Where(t => t.ID == currentTerm.ID)
    .SingleOrDefault();

在日志中,我看到了查询的预期 SQL,并且得到了预期的Person实例,但是当我访问 Registrations 集合时,会(延迟)加载完整的注册集合。我期待它只是符合标准的注册的部分集合。

上一个问题Fetch()中,我遇到了相反的问题,并通过在查询中添加子句来修复它。

JoinQueryOver 条件什么时候会导致根实体有部分集合,什么时候它有一个将被延迟加载的未加载集合?我觉得我应该明白这一点。

我的流利映射Person

public class PersonMapping : ClassMap<Person>
{
    public PersonMapping()
    {
        Id(x => x.ID).GeneratedBy.Guid();
        Map(x => x.Username).Length(20).Unique();
        Map(x => x.HashedPassword).Length(Security.HashedPasswordEncodedLength);
        Map(x => x.PasswordSalt).Length(Security.PasswordSaltEncodedLength);
        Map(x => x.LastName).Length(25).Index("FullName");
        Map(x => x.FirstName).Length(20).Index("FullName");
        Map(x => x.StudentID).Length(12).Nullable();
        Map(x => x.EmployeeID).Length(12).Nullable();
        Map(x => x.EmailAddress).Length(72);
        Map(x => x.IsAdmin).Nullable();
        Map(x => x.IsAgencyStaff).Nullable();
        Map(x => x.IsCenterStaff).Nullable();
        Map(x => x.IsFaculty).Nullable();
        Map(x => x.IsRegistrant).Nullable();
        Map(x => x.IsStudent).Nullable();

        Map(x => x.Type);
        Map(x => x.AuthenticationMode);

        HasMany<Registration>(x => x.Registrations).KeyColumn("Registrant_id")
            .LazyLoad()
            .AsBag()
            .Inverse()
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.SaveUpdate();
    }
}

更新 将此与我的另一个问题(上面链接)进行比较,我遇到了相反的问题,即使用 aLeft.JoinQueryOver从基础实体获取集合。我在这里尝试过,然后得到了预期的部分集合。(在另一种情况下,我实际上不需要左连接;我不记得它为什么在那里。)

获取的记录在有或没有左连接的情况下是相同的,但 NHibernate 在一种情况下填充集合,而不是在另一种情况下。我怀疑这是我可以依赖的行为,所以我改变了我的策略,分别查询注册。

4

1 回答 1

1

这种情况在QueryOver

...
.JoinQueryOver<Registration>(p => p.Registrations)
.Where(r => r.IsDropped == false)
...

实际上是Person的 WHERE 子句。我的意思是,这个条件决定是否存在这样的Person,至少有一个没有Registration被丢弃。这不是一种方法,如何过滤注册集合。但:

NHibernate 有两种很好的方法来过滤集合。这些是where子句和filter

1.where子句

简单地说:我们可以扩展集合映射,用一条 SQL 语句,它总是作为 where 条件添加。见6.2. 映射一个 Collection,提取:

where="arbitrary sql where condition" ==(可选)指定检索或删除集合时要使用的任意 SQL WHERE 条件(如果集合应仅包含可用数据的子集,则很有用)

所以在我们的例子中,映射:

HasMany<Registration>(
  ...
  .Where("IsDropped = 0"); // SQL Statement

2.过滤器设置

虽然where子句是静态的,但烘焙到程序集/映射...过滤器是一种动态执行此操作的方法。所以想象一下,我们有时希望有一组Registrations,下一次被丢弃,没有被丢弃。

我们希望能够更改"IsDropped = 0""IsDropped = 1" (更好的方案可能是按文化或语言切换)。这就是可以应用过滤器的地方,见18.1。NHibernate 过滤器

有一个带有 fluent 的过滤器的小草稿,请参阅下面的链接以获得完整的图片。

HasMany
  ...
  .ApplyFilter<MyFilter>()

过滤器可能像:

public class MyFilter: FilterDefinition
{
    public MyFilter()
    {
        WithName("dropped")
          .WithCondition("IsDropped == :isDropped")
          .AddParameter("isDropped", NHibernate.NHibernateUtil.Boolean);
    }
}

最后,我们可以为整个会话启用过滤器(酷,所有集合将在该事务/会话中以相同的方式过滤,所有集合映射为MyFilter

session.EnableFilter("dropped").SetParameter("isDropped", false);

在这里查看更多:

于 2013-11-14T03:58:49.080 回答