title: Fluent NHibernate automapping composite id with component
body: <p>I have this complex situation: a database of countries/regions/states/cities which primary key is composed by a code (nvarchar(3)) in a column called "Id" plus all key columns of "ancestors" (regions/states/cities).</p>
  
  <p>So the table country has only one key coumn (Id) while cities has 4 key columns (Id, StateId,regionId,CountryId). Obviously they're all related, so each ancestor column is a foreign key to the related table.</p>
  
  <p>I have Entities in my Model that map this relationships. But they all derive from one type called Entity&lt;T&gt;  where T may be a simple type (string, in etc) or a complex one (a component implementing the key).
  Entity&lt;T&gt; implements a single property called Id of type T.</p>
  
  <p>For each db table, if it has a comlex key, I implement it in a separate component, which oveerides also Equals and GetHashCode() Methods (in future I'll implement those in the Entity base class).</p>
  
  <p>So I have a RegionKey componet that has 2 properties (Id and CountryId).
  I have conventions for Foreign Key and primary key naming and type and that is ok.
  I have also Mapping ovverrides for each complex Entity.</p>
  
  <p>For simplicity, lets concentrate only on Countries and Regions table. Here they are:</p>
  
  <pre><code>public class Country: Entity&lt;string&gt;
  {
      public virtual string Name { get; set; }
      public virtual IList&lt;Region&gt; Regions { get; set; } 
  }
  
   public class Region: Entity&lt;RegionKey&gt;
  {
      public virtual string Name { get; set; }
      public virtual Country Country { get; set; }
  }
  </code></pre>
  
  <p>and the RegionKey component:</p>
  
  <pre><code>namespace Hell.RealHellState.Api.Entities.Keys
  {
    [Serializable]
    public class RegionKey
    {
      public virtual string Id { get; set; }
      public virtual string CountryId { get; set; }
  
      public override bool Equals(object obj)
      {
          if (obj == null)
              return false;
          var t = obj as RegionKey;
          if (t == null)
              return false;
          return Id == t.Id &amp;&amp; CountryId == t.CountryId;
      }
  
      public override int GetHashCode()
      {
          return (Id + "|" + CountryId).GetHashCode();
      } 
    }
  }
  </code></pre>
  
  <p>Here is the configuration of AutoPersistenceModel:</p>
  
  <pre><code>    public ISessionFactory CreateSessionFactory()
      {
          return Fluently.Configure()
            .Database(
              MsSqlCeConfiguration.Standard
              .ConnectionString(x=&gt;x.Is(_connectionString))
            )
            .Mappings(m =&gt; m.AutoMappings.Add(AutoMappings))
            .ExposeConfiguration(BuildSchema)
            .BuildSessionFactory();
      }
  
      private AutoPersistenceModel AutoMappings()
      {
          return AutoMap.Assembly(typeof (Country).Assembly)
              .IgnoreBase(typeof(Entity&lt;&gt;))
              .Conventions.AddFromAssemblyOf&lt;DataFacility&gt;()
              .UseOverridesFromAssembly(GetType().Assembly)
              .Where(type =&gt; type.Namespace.EndsWith("Entities"));
      }
  
      private static void BuildSchema(Configuration config)
      {
          //Creates database structure
          new SchemaExport(config).Create(false, true);
          //new SchemaUpdate(config).Execute(false, true);
      }
  </code></pre>
  
  <p>Here is the Regions entity overrides</p>
  
  <pre><code>public class RegionMappingOverride : IAutoMappingOverride&lt;Region&gt;
  {
      public void Override(AutoMapping&lt;Region&gt; mapping)
      {
          mapping.CompositeId(x=&gt;x.Id)
              .KeyProperty(x =&gt; x.Id, x=&gt; x.ColumnName("Id").Length(3).Type(typeof(string)))
              .KeyProperty(x =&gt; x.CountryId, x =&gt; x.ColumnName("CountryId").Length(3).Type(typeof(string)));
      }
  }
  </code></pre>
  
  <p>Ok now when I test this mapping I got an error saying: The data types of the columns in the relationship do not match.</p>
  
  <p>I have also tried this override:</p>
  
  <pre><code>    public void Override(AutoMapping&lt;Region&gt; mapping)
      {
          mapping.CompositeId()
              .ComponentCompositeIdentifier(x=&gt;x.Id)
              .KeyProperty(x =&gt; x.Id.Id, x=&gt; x.ColumnName("Id").Length(3).Type(typeof(string)))
              .KeyProperty(x =&gt; x.Id.CountryId, x =&gt; x.ColumnName("CountryId").Length(3).Type(typeof(string)));
      }
  </code></pre>
  
  <p>And it almost work but it creates a Regions table with a single column key of varbinary(8000) which is not what I want:</p>
  
  <pre><code>CREATE TABLE [hell_Regions] (
  [Id] varbinary(8000) NOT NULL
  , [Name] nvarchar(50) NULL
  , [CountryId] nvarchar(3) NULL
  );
  GO
  ALTER TABLE [hell_Regions] ADD CONSTRAINT [PK__hell_Regions__0000000000000153] PRIMARY KEY ([Id]);
  GO
  ALTER TABLE [hell_Regions] ADD CONSTRAINT [FK_Regions_Country] FOREIGN KEY ([CountryId]) REFERENCES [hell_Countries]([Id]) ON DELETE NO ACTION ON UPDATE NO ACTION;
  GO
  </code></pre>
  
  <p>I don't have a clue of how to deal with it since it seems to me everythin is ok.</p>
  
  <p>Thanks in advance for your answers</p>