Это заняло много исследований - ключ к поиску ответа - термин «фильтр». Я наткнулся на этот термин, покопавшись в исходном коде NHibernate, начиная с AddJoin, в файле ANSIJoinFragment.cs - код поддерживает дополнительные условия для объединения, поэтому я решил, что это возможно.
В любом случае, вот пересмотренный код, который использует фильтр (класс сущности остается тем же).
Repository:
IList<Parent> foundParents = new List<Parent>();
var criteria1 = DetachedCriteria.For<Parent>()
.Add(Restrictions.Eq("ParentId", parentId))
.CreateCriteria("Children", JoinType.LeftOuterJoin);
Session.EnableFilter("dateFilter")
.SetParameter("startDate", startDate)
.SetParameter("endDate", endDate);
foundParents = Session
.CreateMultiCriteria()
.Add<Parent>(criteria1)
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.List()[0] as List<Parent>;
Мне также пришлось изменить отображение для Parent, добавив элементы filter и filter-def.
<class name="Parent" table="Parents">
...
<bag name="Children" table="Children">
...
<filter name="dateFilter"
condition="ChildDate BETWEEN :startDate and :endDate" />
</bag>
</class>
<filter-def name="dateFilter">
<filter-param name="startDate" type="System.DateTime" />
<filter-param name="endDate" type="System.DateTime" />
</filter-def>
Кроме того, одно слово предупреждения для тех, кто сталкивается с этой проблемой и не использует фильтры. Если вы решите вернуть родительский объект без заполненных дочерних элементов, когда исходный запрос с предложением where не даст записей, любой код, который попадет в набор дочерних элементов, заставит NHibernate загрузить всю таблицу.