I have a search-method which returns multiple items, each with several child-properties with references to other tables.
For the child-property that is a collection everything works as I want it to but how can I do the same for the one-to-one children?
Here is some stubs and some of the code I tried:
public class Request {
//HasMany(x => x.Examinations).Access.CamelCaseField().Cascade.All().BatchSize(100);
public virtual IList<Examination> Examinations;
//References(x => x.Creator, "rem_creator_userid");
public virtual User Creator { get; private set; }
}
public class RepositoryExample {
// This search will ask one nice-looking query to the database fetchning all the
// requests
// Then it will ask ONE query fetching the Examinations from the database
// Then it will ask N+1 questions fetching Creator from all Requests
public IList<Request> Search1(ListRequestSearchConditions searchConditions) {
var query =
from request in Session.Query<Request>()
from exam in request.Examinations
where
searchConditions.Units.Contains(request.ReferralSource) &&
exam.Status.HasValue &&
exam.Status.Value >= ExaminationStatus.Value.RequestSubmitted &&
request.PatientId != null
select request;
return query
.Skip((searchConditions.Page - 1) * searchConditions.PageSize)
.Take(searchConditions.PageSize)
.ToList();
}
// This search with ask one slow join-query fetching everything from the database
public IList<Request> Search2(ListRequestSearchConditions searchConditions) {
Examination examinationAlias = null;
return Session.QueryOver<Request>()
.WhereRestrictionOn(request => request.ReferralSource).IsIn(searchConditions.Units)
.Where(request => request.PatientId != null)
.JoinAlias(request => request.Examinations, () => examinationAlias)
.Where(() => examinationAlias.Status.Value != null)
.Where(() => examinationAlias.Status.Value >= ExaminationStatus.Value.RequestSubmitted)
.Skip((searchConditions.Page - 1) * searchConditions.PageSize)
.Take(searchConditions.PageSize)
.ToList();
}
// This search will first ask ONE query joining Request with Examinations
// Then it will ask ONE query fetching the Examinations from the database
// Then it will ask N+1 queries fetching Creator from all Requests
public IList<Request> Search3(ListRequestSearchConditions searchConditions) {
Examination examinationAlias = null;
return Session.QueryOver<Request>()
.WhereRestrictionOn(request => request.ReferralSource).IsIn(searchConditions.Units)
.Where(request => request.PatientId != null)
.JoinAlias(request => request.Examinations, () => examinationAlias)
.Where(() => examinationAlias.Status.Value != null)
.Where(() => examinationAlias.Status.Value >= ExaminationStatus.Value.RequestSubmitted)
.Fetch(request => request.Examinations).Lazy
.Fetch(request => examinationAlias.ExaminationType).Lazy;
.Skip((searchConditions.Page - 1) * searchConditions.PageSize)
.Take(searchConditions.PageSize)
.ToList();
}
}
I hope that is possible to do this in 3 queries, one fetching the list of Requests, one fetching the Examinations and one fetching the Creators.
If you don’t want to have it in one single query (using
Fetch/ThenFetchin LINQ) and use batching instead, you have to specify it atCreatormapping level. Batch size can’t be defined at query level.In Fluent NHibernate you can just add
BatchSize(100)in yourCreatormapping.