This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.
If you want to have lazy properties on your entity, your entities must also be lazy. This applies to basic type or array type properties (typically String or Byte mapped to CLOB or BLOB columns) as well as entity type references (one to one, many to one). This is because NHibernate will only create proxies (in practice, subclasses created at runtime that override the lazy properties) for entities marked as lazy. These properties, of course, must be declared as virtual, and need to be public, protected or protected internal, private or internal wont work, and the classes cannot be sealed.
A different matter is lazy collections (one to many): for these, classes don’t need to be inherited from as NHibernate will change the collection properties for their own collection classes that already implements the lazy behavior. These collection properties must though be declared as interfaces (IEnumerable<T>, ICollection<T>, IList<T>, Iesi.Collections.Generic.ISet<T>), not actual types, so that they can be assigned to NHibernate classes, which also implement these interfaces.