I've got a model where a Person
has a lazy-loaded collection of Registration
s. My NHibernate 3.3.3 query uses JoinQueryOver
across that relation and some more:
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();
In the log, I see the expected SQL for the query, and I get the expected Person
instance, but when I access the Registrations collection, the full collection of registrations gets (lazy) loaded. I was expecting it would just be a partial collection of the registrations that meet the criteria.
In a previous question, I had the opposite problem, and fixed it by adding a Fetch()
clause to the query.
When does a JoinQueryOver criterion cause the root entity to have a partial collection, and when does it have an unloaded collection that will get lazy loaded? I feel like I should understand this.
My fluent mapping for 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();
}
}
Update
Comparing this with my other question (linked above), where I had the opposite problem, that one uses a Left.JoinQueryOver
to get from the base entity to the collection. I tried that here, and then got the expected partial collection. (I don't actually need the left join in the other case; I don't remember why it's there.)
The records fetched are the same with or without the left join, but NHibernate populates the collection in one case, and not in the other. I doubt that's behavior I can depend on, so I've changed my strategy to query for the registrations separately.