nhibernatemany-to-manynhibernate-mappingnhibernate-mapping-by-code

NHibernate mapping by code ManyToMany


Problem

I'm using NHibernate mapping by code to map relationships. In this case I map users to roles to privileges. Users and roles are in a n:m relationship, same for roles and privileges. The SQL DB is SQL Server. If I remove the n:m relationshop from my code between roles and privileges, my code works. If it is there, I get the following MappingException:

Could not determine type for: 
Dtp.Entities.AppPrivilege, Dtp.Entities, for columns: NHibernate.Mapping.Column(id)

I can't find the source of the difference, since the same relationshop between users and roles works without a hitch. Can anyone shed a light on this problem please?

The precise part which produces the error (it goes away if commented out) is the Bag for AppRole.AppPrivileges.

MyCode

AppUser

~~~ Table ~~~

AppUserId, uniqueidentifier, not null
//some omitted properties

~~~ Entity ~~~

public class AppUser {
    public virtual Guid AppUserId { get; set; }
    //some omitted properties
    public virtual IList<AppRole> AppRoles { get; set; }
}

~~~ Mapping ~~~

public class AppUserMap : ClassMapping<AppUser>
{
    public AppUserMap()
    {
        Table("AppUser");
        Schema("dbo");
        Lazy(true);
        Id(x => x.AppUserId, map => map.Generator(Generators.GuidComb));
        //some omitted properties
        Bag(x => x.AppRoles,
            colmap => {
                colmap.Cascade(Cascade.None);
                colmap.Table("AppUser_AppRole");
                colmap.Key(x => x.Column("AppUserId"));
            },
            map => map.ManyToMany(many => many.Column("AppRoleId")));
    }
}

AppUser_AppRole

~~~ Table ~~~

AppUserId, uniqueidentifier, not null
AppRoleId, uniqueidentifier, not null

AppRole

~~~ Table ~~~

AppRoleId, uniqueidentifier, not null
//some omitted properties

~~~ Entity ~~~

public class AppRole{
    public virtual Guid AppRoleId { get; set; }
    //some omitted properties
    public virtual IList<AppUser> AppUsers { get; set; }
    public virtual IList<AppPrivilege> AppPrivileges { get; set; }
}

~~~ Mapping ~~~

public class AppRoleMap : ClassMapping<AppRole> {

    public AppRoleMap()
    {
        Table("AppRole");
        Schema("dbo");
        Lazy(true);
        Id(x => x.AppRoleId, map => map.Generator(Generators.GuidComb));
        //some omitted properties
        Bag(x => x.AppUsers, 
            colmap => {
                colmap.Cascade(Cascade.None);
                colmap.Table("AppUser_AppRole");
                colmap.Key(x => x.Column("AppRoleId"));
            }, 
            map => map.ManyToMany(many => many.Column("AppUserId")));
        //The following definition produces the bug.
        Bag(x => x.AppPrivileges,
            colmap => {
                colmap.Cascade(Cascade.None);
                colmap.Table("AppRole_AppPrivilege");
                colmap.Key(x => x.Column("AppRoleId"));
            },
            map => map.ManyToMany(many => many.Column("AppPrivilegeId")));
    }
}

AppRole_AppPrivilege

~~~ Table ~~~

AppRoleId, uniqueidentifier, not null
AppPrivilegeId, uniqueidentifier, not null

AppPrivilege

~~~ Table ~~~

AppPrivilegeId, uniqueidentifier, not null
//some omitted properties

~~~ Entity ~~~

public class AppPrivilege {
    public virtual Guid AppPrivilegeId { get; set; }
    //some omitted properties
    public virtual IList<AppRole> AppRoles { get; set; }
}

~~~ Mapping ~~~

public class AppPrivilegeMap: ClassMapping<AppPrivilege> {

    public AppPrivilegeMap()
    {
        Table("AppPrivilege");
        Schema("dbo");
        Lazy(true);
        Id(x => x.AppPrivilegeId, map => map.Generator(Generators.GuidComb));
        //some omitted properties
        Bag(x => x.AppRoles,
            colmap => {
                colmap.Cascade(Cascade.None);
                colmap.Table("AppRole_AppPrivilege");
                colmap.Key(x => x.Column("AppPrivilegeId"));
            },
            map => map.ManyToMany(many => many.Column("AppRoleId")));
    }
}

Solution

  • The answer to this problem cannot be found in the files above. I just forgot to add the AppPrivilegeMap to the ModelMapper during NHibernateHelper.OnConfigure().

    Now the last task is to find out where to put the .Inverse(true), so serializing an object won't result in an exception because of circular reference.