title: How to properly implement Inheritance in EF, with performance in mind
body: <p>My app has <code>Posts</code> and <code>Flags</code>.  Both of these have <code>Responses</code>, which have <code>Comments</code>.  </p>
  
  <pre><code>Post
     Response
        Comment
  Flag
     Response
        Comment
  </code></pre>
  
  <p>I'm trying to model this in EF as simply and properly as possible, but I'm not sure if I'm going overboard here with inheritance.  This is what I have: </p>
  
  <pre><code>public class Post {
      [Key]
      [Required]
      public int PostId { get; set; }
      public virtual ICollection&lt;PostResponse&gt; Responses { get; private set; }
  }
  
  public class Flag {
      [Key]
      [Required]
      public int FlagId { get; set; }
      public virtual ICollection&lt;FlagResponse&gt; Responses { get; private set; }
  }
  </code></pre>
  
  <p>I wanted to use just generic <code>Response</code> here, but then my Response class would need to account for both a parent <code>Flag</code> and <code>Post</code>.  Adding both <code>ParentPostId</code> and <code>ParentFlagId</code> to the same class seemed like a dirty way to handle it, especially taking the relationships mapping into account.  So I split Responses up: </p>
  
  <p><strong>High level Message:</strong> </p>
  
  <pre><code>// Comments, Posts, Responses all have these properties
  public abstract class Message {
      [Required]
      public int PosterId { get; set; }
      public virtual User Poster { get; set; }
      public string RawContent { get; set; }            
  }
  </code></pre>
  
  <p><strong>Responses:</strong></p>
  
  <pre><code>public abstract class Response : Message {
      [Key]
      [Required]
      public int ResponseId { get; set; }
      public virtual ICollection&lt;Comment&gt; Comments { get; set; } 
  }
  // will be used by Posts only
  public class PostResponse : Response {
      [Required]
      public int ParentPostId { get; set; }
      public virtual Post Post { get; set; }
  }
  // will be used by Flags only
  public class FlagResponse : Response {
      [Required]
      public int ParentFlagId { get; set; }
      public virtual Flag Flag { get; set; }
  }
  </code></pre>
  
  <p>So see, then I had to account for the difference in Comments:</p>
  
  <p><strong>Comments:</strong></p>
  
  <pre><code>public abstract class Comment : Message {
      [Key]
      [Required]
      public int CommentId { get; set; }
  }
  // will be used by PostResponses only
  public class PostComment : Comment {
      [Required]
      public int ResponseId { get; set; }
      public virtual PostResponse Response { get; set; }
  }
  // will be used by FlagResponses only
  public class FlagComment : Comment {
      [Required]
      public int ResponseId { get; set; }
      public virtual PostResponse Response { get; set; }
  }
  </code></pre>
  
  <p>So I've fattened up my schema and now my FluentAPI codefirst configurations are going to get tricky, but my logic can now easily distinguish between types and the data is normalized.</p>
  
  <p>It <em>feels</em> less smelly than packing everything into a single model, but I'm not sure if this is even close to a best practice, especially with performance concerns.  Performance is the highest priority with the design.</p>
  
  <p><strong>Update</strong></p>
  
  <p>After spending nearly the entire afternoon on trying to implement TPH inheritance with Code-First, I've thrown my hands up.  See this question: </p>
  
  <p><a href="https://stackoverflow.com/questions/20446856/ef-inheritance-and-foreign-keys?lq=1">EF Inheritance and Foreign Keys</a></p>
  
  <p>So I think the cheapest and post performant solution would be for me to add optional FK Ids to the Response object - one for FlagId and the other for PostId.  Beef up my validation a bit, be the opposite of normalized, but stay away from complicating my schema and introducing more joins for queries in TPC or TPT, and avoid the hating-myself that comes with TPH in this scenario.  I think what I'm doing is brute-force TPH anyways.  </p>
  
  <p>I'll keep this up in case anyone has any suggestions or in case this can spare anyone else from the anguish I've experienced today.  </p>