什么时候NHibernate JoinQueryOver加载完整的集合?

时间:2013-11-14 01:03:17

标签: nhibernate fluent-nhibernate queryover

我有一个模型,其中Person有一个延迟加载的Registration s集合。我的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集合时,完整的注册集合被加载(延迟)。我期待它只是符合条件的注册的部分集合。

a previous question中,我遇到了相反的问题,并通过在查询中添加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();
    }
}

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

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

1 个答案:

答案 0 :(得分:1)

QueryOver中的这种情况:

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

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

NHibernate有两种好方法如何自己过滤集合。这些是 where 子句和过滤器

1。 where子句

轻松说:我们可以扩展集合映射,一个SQL语句,它将始终作为where条件添加。查看6.2. Mapping a Collection的位置,提取:

  

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

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

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

2。过滤器设置

虽然其中子句是静态的,但在程序集/映射...过滤器中是一种如何动态执行此操作的方法。所以想象一下,我们有时希望有一组Registrations,这些被删除,下次,掉线。

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

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

HasMany
  ...
  .ApplyFilter<MyFilter>()

过滤器可能就像:

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

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

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

在此处查看更多信息: