title: Entity framework 6 custom keys for table-per-type inheritance
body: <p>I need to transform some existing DB under a new application using EF6 with the CodeFirst approach. I am fighting with mapping conventions in inheritance. There is a minimal (not)working example:</p>
  
  <p>Assume I have two tables: a Parent and a Child.</p>
  
  <pre><code>CREATE TABLE A_PARENT (
      A_PAR_ParentId UNIQUEIDENTIFIER PRIMARY KEY,
      A_PAR_data VARCHAR(255)
  )
  
  CREATE TABLE B_CHILD (
     B_CHL_ChildId UNIQUEIDENTIFIER PRIMARY KEY FOREIGN KEY REFERENCES A_PARENT(A_PAR_ParentId),
     B_CHL_childData VARCHAR(255)
  )
  </code></pre>
  
  <p>I successfuly solved the table prefices you can see, such the "A_PAR" using custom attributes. I believe the EF exactly knows what property belongs to which column and which one is the primary key. Everything works fine except for inheritance. Because when I attempt to get all of Children, I end up with a SQL error, because the EF produces a query like this:</p>
  
  <pre><code>SELECT 
      '0X0X' AS [C1], 
      [Extent1].[A_PAR_ParentId] AS [A_PAR_ParentId], 
      [Extent1].[A_PAR_Data] AS [A_PAR_Data], 
      [Extent2].[B_CHL_ChildId] AS [B_CHL_ChildId], 
      [Extent2].[B_CHL_ChildData] AS [B_CHL_ChildData]
      FROM  [dbo].[A_PARENT] AS [Extent1]
      INNER JOIN [dbo].[B_CHILD] AS [Extent2] ON [Extent1].[A_PAR_ParentId] = [Extent2].[A_PAR_ParentId]
  </code></pre>
  
  <p>The only incorrect thing in the query is the join predicate - there is no such a column <code>A_PAR_ParentId</code> in the table <code>B_CHILD</code>.</p>
  
  <p>How can I force the EntityFramework to use entity's primary key to use as a foreign key when constructing the inheritance chain? I am looking for some general solution based on conventions because all of the tables in the DB are using this pattern (if the type/table is inherited => the primary key is a foreign key to parent's primary key and there are no composite keys at all). Maybe I am looking for some way to tell the EF the PK is also a FK but without a navigation property.</p>
  
  <p>--Edit: more code</p>
  
  <p>The model is pretty simple:</p>
  
  <pre><code>    [ModulePrefix("A"), TablePrefix("PAR")]
      public class Parent
      {
          public Guid ParentId { get; set; }
          public string Data { get; set; }
      }
  
      [ModulePrefix("B"), TablePrefix("CHL")]
      public class Child : Parent
      {
          public Guid ChildId { get; set; }
          public string ChildData { get; set; }
      }
  </code></pre>
  
  <p>And the configuration:</p>
  
  <pre><code>protected override void OnModelCreating(DbModelBuilder modelBuilder)
          {
              base.OnModelCreating(modelBuilder);
              modelBuilder.Conventions.Remove&lt;PluralizingTableNameConvention&gt;();
  
              modelBuilder.Types()
                  .Where(type =&gt; !type.GetCustomAttributes(false).OfType&lt;TableAttribute&gt;().Any() &amp;&amp; type.GetCustomAttributes(false).OfType&lt;ModulePrefixAttribute&gt;().Any())
                  .Configure(config =&gt; config.ToTable(
                      ComposeDbName(GetModulePrefix(config.ClrType),
                      CamelCaseToUnderscore(GetClassName(config.ClrType)).ToUpper())
                      ));
  
              modelBuilder.Properties()
                  .Where(property =&gt; property.DeclaringType.GetCustomAttributes(false).OfType&lt;TablePrefixAttribute&gt;().Any() &amp;&amp; property.DeclaringType == property.ReflectedType)
                  .Configure(config =&gt; config.HasColumnName(ComposeDbName(
                      GetModulePrefix(config.ClrPropertyInfo.DeclaringType),
                      GetTablePrefix(config.ClrPropertyInfo.DeclaringType),
                      config.ClrPropertyInfo.Name
                      )));
              modelBuilder.Properties()
                  .Where(property =&gt; property.Name == property.DeclaringType.Name + "Id" &amp;&amp; property.ReflectedType == property.DeclaringType)
                  .Configure(config =&gt; config.IsKey());
  
              modelBuilder.Properties()
                  .Where(property =&gt; property.PropertyType.IsClass || Nullable.GetUnderlyingType(property.PropertyType) != null)
                  .Configure(config =&gt; config.IsOptional());
          }
  </code></pre>
  
  <p>There are some more private methods playing with columns/tables names. I think thats not important at this point since column/table names appear to be resolved well.</p>