Dav Evans
Dav Evans

Reputation: 4071

NHibernate Map many-to-many join table

My database structure looks something like this:

Person
  Id
  Name
  FieldA
  FieldB

Phone
  Id
  Number

PersonPhone
  PhoneId
  PersonId
  IsDefault

My NHibernate mappings for the Person and Phone objects are straight forward, its the PersonPhone I'm having difficult with. I want to have a collection of PersonPhone objects as a property of Person which will allow me to have the Phone number of a person and be able to tell which is the "default" or primary phone number for a person.

ideally Id like my PersonPhone object to look like this:

public class PersonPhone
{
    public virtual Person Person { get; set; }
    public virtual Phone Phone { get; set; }
    public virtual bool IsDefault { get; set; }
}

so far my NHibernate mapping for this table looks like the following:

<class name="PersonPhone" table="PersonPhone">
    <composite-id>
        <key-property name="Person" column="PersonId" />
        <key-property name="Phone" column="PhoneId" />
    </composite-id>
    <property name="IsDefault" column="IsDefault"/>
</class>

but when NHibernate compiles my mappings I get an error saying:

Could not compile the mapping document: MyApp.Entities.PersonPhone.hbm.xml. NHibernate.MappingException : Could not determine type for: MyApp.Entities.Person, MyApp.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null, for columns: NHibernate.Mapping.Column(PersonId)

Any ideas on how this should be mapped?

Upvotes: 3

Views: 8649

Answers (3)

Samuel Jack
Samuel Jack

Reputation: 33300

To set-up the same mapping with Fluent NHibernate, do this:

public class PersonPhoneMap : ClassMap<PersonPhone>
{
    public PersonPhoneMap()
    {
        CompositeId()
            .KeyReference(p => m.Person)
            .KeyReference(p => m.Phone);

        References(p => p.Person)
            .Column("PersonID");
        References(m => m.Phone)
            .Column("PhoneID");
        Map(p => p.IsDefault)
            .Column("IsDefault");
    }
}

Upvotes: 3

Wahid Shalaly
Wahid Shalaly

Reputation: 2187

I think It is more proper to consider Many-to-Many relationship between Phone and Peron entities and get rid of PersonPhone entity.

Upvotes: 3

Dav Evans
Dav Evans

Reputation: 4071

The answer is to use the element in your composite key rather than the key-property

<class name="PersonPhone" table="PersonPhone">
    <composite-id>
        <key-many-to-one name="Person" column="PersonId"></key-many-to-one>
        <key-many-to-one name="Phone" column="PhoneId"></key-many-to-one>
    </composite-id>
    <property name="IsDefault" column="IsDefault"/>
</class>

Upvotes: 6

Related Questions