I would suggest, at least in this case, use the mapping close to the DB structure. Which does not seem to be so bad. We should have a User
which has a ProfileProperty
collection. Each ProfileProperty
has a reference to ProfileField
<class name="User" ...>
...
<set name="ProfileProperties" lazy="true">
<key column="UserId" />
<one-to-many class="ProfileProperty"/>
</set>
</class>
<class name="ProfileProperty" ...>
...
<many-to-one class="ProfileField" column="FieldId" />
</class>
<class name="ProfileField" ... />
the C# :
public class User
{
public virtual IList<ProfileProperty> ProfileProperties { get; set; }
...
public class ProfileProperty
{
public virtual ProfileField ProfileField { get; set; }
...
public class ProfileField
{
public virtual string Name { get; set; }
...
This is a native structure. This way we can use the power of the NHibernate querying. And also the Write operations will go smoothly.
If you really need that artificial collection, NHibernate has solution as well. It would be readonly, but in some scenarios it could help...
The way to go here, if we really would like to solve it on the mapping layer, is <subselect>
and <composite-element>
<bag name="UserProperties">
<subselect>
select
profilefield.fieldid, AS FieldId
profilefield.Name, AS Name
ProfileProperty.Value, AS Value
profileproperty.userid AS UserId
from profilefield,
profileproperty
where profilefield.fieldid=profileproperty.fieldid
</subselect>
<key column="UserId" />
<composite-element class="UserProperty" >
<parent name="Parent" />
<property name="FieldId" />
<property name="Name" />
<property name="Value" />
</composite-element>
</bag>
and C# :
public class UserProperty
{
public virtual User Parent { get; set; }
public virtual string Name { get; set; }
public virtual string Value { get; set; }
public virtual int FieldId { get; set; }
}