我有一个模型,其中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在一个案例中填充集合,而不在另一个案例中填充。我怀疑我可以依赖的行为,所以我改变了我的策略来单独查询注册。
答案 0 :(得分:1)
QueryOver
中的这种情况:
...
.JoinQueryOver<Registration>(p => p.Registrations)
.Where(r => r.IsDropped == false)
...
实际上是 Person 的WHERE子句。我的意思是,这个条件决定是否有这样的Person
,至少有一个Registration
NOT 被删除。这不是一种方法,如何过滤注册集合。但是:
NHibernate有两种好方法如何自己过滤集合。这些是 where 子句和过滤器。
轻松说:我们可以扩展集合映射,一个SQL语句,它将始终作为where条件添加。查看6.2. Mapping a Collection的位置,提取:
where="arbitrary sql where condition"
==(可选)指定在检索或删除集合时要使用的任意SQL WHERE条件(如果集合应该有用) 仅包含可用数据的子集)
所以在我们的例子中是映射:
HasMany<Registration>(
...
.Where("IsDropped = 0"); // SQL Statement
虽然其中子句是静态的,但在程序集/映射...过滤器中是一种如何动态执行此操作的方法。所以想象一下,我们有时希望有一组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);
在此处查看更多信息: