title: Fluent NHibernate Mapping - Composite Key
body: <p>I'm trying to map the following tables/entities in FNH and seem to be getting nowhere fast!</p>
  
  <pre><code>**Tables**
  Contacts
      ID (PK - int - generated)
      ...
  
  PhoneTypes
      ID (PK - varchar - assigned) (e.g. MOBILE, FAX)
  
  ContactPhones
      ContactRefId    (PK - FK to Contacts)
      PhoneTypeRefId  (PK - FK to PhoneTypes)
      ...
  </code></pre>
  
  <p>(I should note that I am also using the S#arp Architecture framework)</p>
  
  <pre><code>**Entities**
  public class Contact : Entity
  {
      (The ID property is defined in the Entity base class and is type int)
  
      public virtual ICollection&lt;ContactPhone&gt; PhoneNumbers { get; set; }
  }
  
  public class PhoneType : EntityWithTypedId&lt;string&gt;, IHasAssignedId&lt;string&gt;
  {
      (The ID property is defined in the base class and is type string)
  
      ....
  }
  
  public class ContactPhone : EntityWithTypedId&lt;ContactPhoneId&gt;, IHasAssignedId&lt;ContactPhoneId&gt;
  {
      public virtual Contact Contact { get; set; }
  
      public virtual PhoneType PhoneType { get; set; }
      ....
  }
  </code></pre>
  
  <p>I read that it is advisable when working with composite ids, to separate the composite id into a different class.
  <a href="https://stackoverflow.com/questions/2301259/hibernate-composite-key/2301332#2301332">hibernate composite key</a></p>
  
  <pre><code>public class ContactPhoneId : EntityWithTypedId&lt;ContactPhoneId&gt;, IHasAssignedId&lt;ContactPhoneId&gt;
  {
      public virtual Contact Contact { get; set; }
  
      public virtual PhoneType PhoneType { get; set; }
  }
  ...I could just make this class serializable and override 
  Equals and GetHashCode myself instead of using the S#arp Arch base class.
  </code></pre>
  
  <p>I've tried so many combinations of mappings that I'm now completely confused.</p>
  
  <p>This is my latest shot:</p>
  
  <pre><code>public class ContactMap : IAutoMappingOverride&lt;Contact&gt;
  {
      public void Override(AutoMapping&lt;Contact&gt; mapping)
      {
          mapping.HasMany&lt;ContactPhone&gt;(x =&gt; x.PhoneNumbers)
              .KeyColumns.Add("ContactRefId")
              .KeyColumns.Add("PhoneTypeRefId")
              .AsSet()
              .Inverse()
              .Cascade.All();
      }
  }
  
  
  public class PhoneTypeMap : IAutoMappingOverride&lt;PhoneType&gt;
  {
      public void Override(AutoMapping&lt;PhoneType&gt; mapping)
      {
          mapping.Id(x =&gt; x.Id).Column("Id").GeneratedBy.Assigned();
      }
  }
  
  
  public class ContactPhoneMap : IAutoMappingOverride&lt;ContactPhone&gt;
  {
      public void Override(AutoMapping&lt;ContactPhone&gt; mapping)
      {
          mapping.Table("ContactPhones");
          mapping.CompositeId&lt;ContactPhoneId&gt;(x =&gt; x.Id)
              .KeyReference(y =&gt; y.Contact, "ContactRefId")
              .KeyReference(y =&gt; y.PhoneType, "PhoneTypeRefId");
      }
  }  
  </code></pre>
  
  <p>I've had many exceptions thrown when trying to generate the mappings, the latest of which is:</p>
  
  <pre><code>Foreign key (FK672D91AE7F050F12:ContactPhones [ContactRefId, PhoneTypeRefId])) 
  must have same number of columns as the referenced primary key (Contacts [Id])
  </code></pre>
  
  <p>Does anyone see anything obvious that I'm doing wrong? I'm new to NH and FNH, which may be obvious from this post. :-) Also, has anyone used Composite Ids like this while using S#arp Architecture? What are the best practices (other than to use surrogate keys :-) ) ?</p>
  
  <p>Many thanks...and sorry about the long post.</p>