Andrew
Andrew

Reputation: 5126

Is this a legitimate use of TPC inheritance in EF Code First?

I'm designing a fairly complex hosted web app that needs to support multiple "Teams" that are effectively isolated from each other. For example, the tables People, Areas, Reports, etc. will have intermingled data populated by the teams at Corporation A, B, C, and on down the line, and the user from Corporation A has logged in, he should only ever see data relevant to corporation A. My plan is to create a relationship between Team and (nearly) every other type and to use a repository to access all those other types, and always query where TeamId matches the TeamId of the person logged in.

So since I want to have

[ForeignKey("Team")]
public int TeamId { get; set; }
public virtual Team Team { get; set; }

on almost every class, I was thinking it might be nice to put those in an abstract class and inherit those properties:

public abstract class OfTeam {
    [ForeignKey("Team")]
    public int TeamId { get; set; }
    public virtual Team Team { get; set; }
}

public class Person : OfTeam {
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

But, I realize this isn't truly what inheritance is about. So I'd like to know

  1. Will this even work?
  2. Is it a terrible idea?

Upvotes: 0

Views: 89

Answers (1)

AaronLS
AaronLS

Reputation: 38367

I misunderstood at first and though you were inheriting team, which would have been a bad idea.

If you ever query db.OfTeam then it will union together every single table that inherits from it, which will perform terribly. Scroll down to see the SQL produced here: http://weblogs.asp.net/manavi/archive/2011/01/03/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines.aspx

Otherwise the actual DB structure should be identical to if you simply put TeamId/Team on all of those classes directly.

I personally wouldn't do this because it adds little value and could potentially cause headaches down the road.

Instead you could just have an IOfTeam interface on all those classes if there is a need to interact with them in a generic manner for some reason.

As a side note I've done something similar and usually cache TeamId somewhere easily accessible, such that I can anywhere do CurrentIdentity.TeamId and pass it to a query. This allows methods on repository pattern like GetPeople to apply a where criteria with that filter before returning the IQueryable.

Upvotes: 1

Related Questions