I have a class Unit
with a Dictionary
of Parts
. The mapping looks like this
<class name="Unit" table="Units">
<id name="Id">
<generator class="native"/>
</id>
<property name="CreationDate" />
<property name="MacAddress" />
<property name="OEMId" />
<property name="SerialNumber" />
<property name="QualityControlState" />
<map name="Parts" table="UnitParts" lazy="false">
<key column="UnitId"/>
<index column="TypeOfPart" type="integer"/>
<composite-element class="UnitPart">
<property name="PartInfo"/>
<property name="Remarks"/>
</composite-element>
</map>
When I Session.SaveOrUpdate(Unit)
all goes well: the two tables are filled with the right data. And the unit is retreivable (with all its Parts
) using Session.Get(typeof(Unit)
as well.
The problem: Obtaining multiple units lazy loads the Parts
Dictionary
.
The problem rephrased in pseudo code: LoadMethodOfPartsDictionary = (Stepping with Debugger) ? Eagerly : Lazy;
The following code baffles me. When I step through it using the debugger the Parts
Dictionary
of a Unit
is eagerly loaded. But when I run to return Units
(not stepping through Units = crit.Future<Unit>().ToList<Unit>();
) its seems NHibernate wants to lazy load as the Parts
Dictionary
suddenly is NHibernate.Collection.Generic.PersistentGenericMap
.
/// <summary>
/// Retreives a list of units by a set of criteria.
/// </summary>
/// <returns>A list of units that fall within/match the criteria</returns>
public static List<Unit> GetUnits(List<KeyValuePair<Unit.SortableProperties, ListSortDirection>> SortColumnOrder, out uint NumberOfRecordsWithoutLimit, uint Start = 0, int End = -1, FilterUnits Filter = default(FilterUnits))
{
List<Unit> Units = default(List<Unit>);
NumberOfRecordsWithoutLimit = 0;
using (ISession Session = ORM.SessionFactory.OpenSession())
{
using (ITransaction Transaction = Session.BeginTransaction())
{
ICriteria crit = Session.CreateCriteria<Unit>();
//Limit result set, used for paging
if (End > 0)
{
crit.SetFirstResult((int)Start);
crit.SetMaxResults(End);
}
//TODO: Implement filter code here
//Add the sort order
foreach (KeyValuePair<Unit.SortableProperties, ListSortDirection> kvp in SortColumnOrder)
{
String PropertyName = "";
switch (kvp.Key)
{
case Unit.SortableProperties.PRODUCTIONDATE:
PropertyName = "CreationDate";
break;
default:
throw new NotImplementedException(kvp.Key.ToString() + " isn't implemented for sorting yet.");
}
crit.AddOrder(new Order(PropertyName, (kvp.Value == ListSortDirection.Ascending)));
}
if (End > 0)
{
//Count the total units available in database.
Units = crit.Future<Unit>().ToList<Unit>(); //This seems to lazy load the Units
IFutureValue<int> RowCount = Session.CreateCriteria<Unit>()
.SetProjection(Projections.Count(Projections.Id()))
.FutureValue<int>();
NumberOfRecordsWithoutLimit = (uint)RowCount.Value;
}
else
{
Units = (List<Unit>)crit.List<Unit>();
NumberOfRecordsWithoutLimit = (uint)Units.Count;
}
Transaction.Commit();
Session.Close();
return Units;
}
}
}
Any hints are appreciated.
P.S. I used the [Debugging] tag as this seems to be key in this scenario.