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.

Reply via email to