First we modify our existing stored procedure to return data to populate objects of the new entity as well:
ALTER PROCEDURE [sec].[spGetRelatedUsers] @UserName nvarchar(256), @NumberOfRecords int AS BEGIN -- some processing before the final select -- this can include complex processing using temporary table(s), CTE(s), etc... SELECT DISTINCT TOP (@NumberOfRecords) U.* , R.* , A.* FROM Users U INNER JOIN Roles R ON U.RoleId=R.RoleId LEFT JOIN Attributes A ON A.UserId=U.UserId -- other joins and conditions END
Then we create the new entity class:
public class UserAttribute { public int AttributeId { get; set; } public User User { get; set; } // link to the main entity public string DisplayName { get; set; } public string Code { get; set; } }
And its .hbm.xml mapping file:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping assembly="MyAssemblyName" namespace="MyNamespace" xmlns="urn:nhibernate-mapping-MyNHibernateVersionNumber"> <class name="UserAttribute" lazy="false"> <id name="AttributeId"> <generator class="identity" /> </id> <many-to-one name="User" column="UserId" not-null="true"/> <!-- specify relationship to the main entity --> <property name="DisplayName" /> <property name="Code" /> </class> </hibernate-mapping>
We also link the new entity from our main entity:
public class User { public long UserId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime? DOB { get; set; } public UserRole Role { get; set; } public IList<UserAttribute> Attributes { get; set; } // link to the new entity }
Also modify the main entity's mapping file to specify the relationship with the new entity. In this case we use bag collection mapping:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping assembly="MyAssemblyName" namespace="MyNamespace" xmlns="urn:nhibernate-mapping-2.2"> <class name="User" lazy="false"> <id name="UserId"> <generator class="identity" /> </id> <property name="FirstName" /> <property name="LastName" /> <property name="DOB" column="DateOfBirth" /> <component name="Role" class="UserRole"> <property name="RoleId"> <column name="RoleId" /> </property> <property name="Name" /> <property name="Description" /> <property name="Active" /> </component> <bag name="Attributes"> <!-- specify relationship to the new entity --> <key column="UserId" /> <one-to-many class="UserAttribute" /> </bag> </class> </hibernate-mapping>
Finally we modify the named query's mapping; add an alias attribute to the existing <return> element then add a new <return-join> element with its alias and property attributes in order to populate the new objects:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping assembly="MyAssemblyName" namespace="MyNamespace" xmlns="urn:nhibernate-mapping-MyNHibernateVersionNumber"> <sql-query name="GetRelatedUsers"> <return alias="U" class="User"></return> <!-- alias is from the one used in the select query --> <return-join alias="A" property="U.Attributes"></return-join> <!-- alias is from the one used in the select query --> exec spGetRelatedUsers :UserName, :NumberOfRecords </sql-query> </hibernate-mapping>
The codes to call the named query remain the same.