Search code examples
nhibernatenhibernate-mapping

NH 3.3 Composite-ID mapping by code


Diagram

I am pulling my hair out here trying to figure out how to map the UsersRoles table listed below. I don't look good bald so please help :)

//Here is the Entity

public class UsersRole
{
    public UsersRole() { }
    public virtual User User { get; set; }
    public virtual Role Role { get; set; }
    public virtual System.Guid UserId { get; set; }
    public virtual System.Guid RoleId { get; set; }


}

//Here is the mapping so far

public class UsersRoleMap : ClassMapping<UsersRole>
{
    public UsersRoleMap()
    {
        Table("UsersRoles");
        Lazy(true);

       // ComponentAsId(); How does this work??


        Property(x => x.UserId, map => map.Column(c =>
            {
                c.Name("UserId");
                c.NotNullable(true);
                c.Length(30);
                c.SqlType("uniqueidentifier");
            }));
        Property(x => x.RoleId, map => map.Column(c =>
            {
                c.Name("RoleId");
                c.NotNullable(true);
                c.Length(30);
                c.SqlType("uniqueidentifier");
            }));
    }
}

Please see the comment in the mapping for ComponentAsId

Thanks in advance if someone can get me on the right track


Solution

  • The method you are looking for is called ComposedId:

    public class UsersRoleMap : ClassMapping<UsersRole>
    {
        public UsersRoleMap()
        {
            ComposedId(map => 
            {
                map.Property(x => x.UserId);
                map.Property(x => x.RoleId);
            });
        }
    }
    

    Answering to your question about how ComponentAsId works. You should have following classes to use ComponentAsId method

    public class UsersRoleId
    {
        public System.Guid UserId { get; set; }
        public System.Guid RoleId { get; set; }
    }
    
    public class UsersRole
    {
        public virtual User User { get; set; }
        public virtual Role Role { get; set; }
        public virtual UsersRoleId Id { get; set; }
    }
    

    And now you could map UsersRole.Id as ComponentAsId

    public class UsersRoleMap : ClassMapping<UsersRole>
    {
        public UsersRoleMap()
        {
            ComponentAsId(x => x.Id);
        }
    }
    

    PS: Why you need to map UsersRoles table? I would suggest you to map users to roles as many-to-many relation.

    public class UsersMap : ClassMapping<User>
    {
        public UsersMap()
        {
            Set(x => x.Roles, x => { }, x => x.ManyToMany());
        }
    }
    
    public class RolesMap : ClassMapping<Role>
    {
        public RolesMap()
        {
            Set(x => x.Users, x => { }, x => x.ManyToMany());
        }
    }