When re-assembling objects from the 2nd level cache that have lazy
properties, we run into cast exceptions, because the sentinel, *
LazyPropertyInitializer.UnfetchedProperty* is deserialized as a new instance
and therefore a reference test will fail:
/// <summary>Deep copy a series of values from one array to
another</summary>
/// <param name="values">The values to copy (the source)</param>
/// <param name="types">The value types</param>
/// <param name="copy">An array indicating which values to include in the
copy</param>
/// <param name="target">The array into which to copy the values</param>
/// <param name="session">The originating session</param>
public static void DeepCopy(object[] values, IType[] types, bool[] copy,
object[] target, ISessionImplementor session)
{
for (int i = 0; i < types.Length; i++)
{
if (copy[i])
{
* if (values[i] == LazyPropertyInitializer.UnfetchedProperty || values[i] ==
BackrefPropertyAccessor.Unknown)*
{
target[i] = values[i];
}
else
{
target[i] = types[i].DeepCopy(values[i], session.EntityMode,
session.Factory);
}
}
}
}
Changing UnfetchedProperty and Unknown to constant Guids and using
Equals(LazyPropertyInitializer.UnfetchedProperty,
values[i]) resolves the issue and all unit tests pass.
It is critical the order of the parameters for Equals is such, so that the
Equals method of Guid is called. Changing the order of the parameters would
call the Equals method of values[i] instead and fail when poorly written
Equals code is encountered. An example is the FooComponent in the unit
tests:
public override bool Equals(object obj)
{
FooComponent fc = (FooComponent) obj;
return Count == fc.Count;
}
Which causes a cast exception by blindly casting obj to FooComponent.