The NHibernate 3.2 collection property is empty while the support field contains items

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:

Debugger view

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> 
+4
source share
2 answers

I just checked issue 2772 and apparently fixed it and it was released in the next major version of NHibernate (which is planned to be called 4.0). Therefore, I mark the question as an answer, albeit a bit premature.

0
source

try using

 bag access="field.camelcase" 

instead

 bag access="nosetter.camelcase" 
+1
source

All Articles