I am using NHibernate 3.2 and I have a problem displaying the collection.
After requesting a user account ...
UserAccount userAccount = (from u in Session.Query<UserAccount>() where u.Username == username select u).SingleOrDefault();
... The Role property contains an empty set, while the roles field contains the actual elements:

Is this a bug in NH 3.2 or something? I'm sure he worked on 3.1.
I believe that the proxy behavior may be wrong, especially the override that handles lazy loading for the roles property. However, I do not know how to check the generated proxy class (using the IL decompiler), since, as far as I know, it lives only in memory at runtime.
EDIT 1
To help me find out what is going on inside the proxy, I just posted this question: Is there a way to decompile proxy classes created by NHibernate? . I think the subject deserves a separate question, because it can be useful in many other situations.
EDIT 2
Well, I was able to decompile the dynamic proxy class. This is the method that controls lazy loading for the roles property:
public override IEnumerable<Role> get_Roles() { IInterceptor interceptor = this.Interceptor; if (interceptor == null) { throw new NotImplementedException(); } object[] args = new object[0]; InvocationInfo info = new InvocationInfo( this, (MethodInfo)methodof(UserAccount.get_Roles), null, new Type[0], args); args = info.Arguments; return (IEnumerable<Role>)interceptor.Intercept(info); }
I donβt think there is anything special here.
EDIT 3
When debugging an interceptor (which is partially shown below), I noticed that when it is called for methodName == "get_Roles" , for the TargetInstance property (which in this case is UserAccount ), it has a roles field representing an empty collection. Right before accessing the roles property in the proxy server instance, however, the proxy Role field has a populated collection.
public class DefaultDynamicLazyFieldInterceptor : IFieldInterceptorAccessor, Proxy.DynamicProxy.IInterceptor { ... public object Intercept(InvocationInfo info) { var methodName = info.TargetMethod.Name; if (FieldInterceptor != null) { ...
When validating an InvocationInfo instance, the proxy and Target instances have a roles field containing a populated collection.
EDIT 4
I think I came across NH Issue 2772 - Lazy collection does not load when the Lazy property is loaded .
END OF EDITING
Here are the entity classes:
public class UserAccount : Entity { ... private IList<Role> roles; public virtual IEnumerable<Role> Roles { get { return roles; } } ... } public class Role : Entity { ... }
Here is the part of the HBM mapping file for UserAccount mapping:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="false" default-cascade="none" default-lazy="true"> <class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" schema="[MySchema]" mutable="true" name="MyNamespace.UserAccount, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="UserAccounts"> ... <bag access="nosetter.camelcase" cascade="none" name="Roles" schema="[MySchema]" table="UserAccounts_Roles" mutable="true"> <key> <column name="UserAccountId" /> </key> <many-to-many class="MyNamespace.Role, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <column name="RoleId" /> </many-to-many> </bag> ... </class> </hibernate-mapping>
And here is the part of HBM that defines role mapping:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="false" default-cascade="none" default-lazy="true"> <class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" schema="[MySchema]" mutable="true" name="MyNamespace.Role, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Roles"> ... </class> </hibernate-mapping>