Grief Coder
Grief Coder

Reputation: 6786

Restrict EF query to a base type with TPT inheritance

Consider the following entity framework model with TPT inheritance.

DB Tables:

Person (PersonID, Name)
Student (PersonID, Grade)

EF Entities:

Person (PersonID, Name)
Student (Grade) : inherits from Person

Now when you're trying to select a person entry from the database it will return Student type instead.

var person = db.Persons.First();
// person here is of type Student and has Grade peoperty populated
// SQL query generated by EF selects data from both tables with a JOIN

How to force this query select only the data from Person db table and not from both Person and Student db tables?

For example, it can be done with the following query:

db.Persons.Select(x => new Person { PersonID = x.PersonID, Name = x.Name }).First() 

but it looks lame, generates an extra SELECT statement over the existing query and this way returned Person entity object will not be tracked by EF context. So, I'm wondering why db.Persons.First() returns a Student object? Isn't it counterintuitive?

Upvotes: 3

Views: 1236

Answers (2)

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364369

If you use a list of Person and stores a single Student to the list what will you receive when you call First? You will receive a Student instance because that is how object oriented code is supposed to work Student is a Person but you will never get just Person instance without creating a new instance and copying data from original Student instance.

EF works in the same way - entity is atomic. It doesn't matter how many tables it spans. If you query inheritance hierarchy you will always get the whole instance of the correct type because that is how object oriented code is supposed to work.

Your second example should not work at all if used in Linq-to-entities because you are creating instance of the entity inside the query - that is not allowed. Projections must not be done to mapped entities because it could break data consistency.

The way to go is using projection either to non entity type - custom not mapped class or anonymous type.

Upvotes: 3

Aghilas Yakoub
Aghilas Yakoub

Reputation: 28990

try with this code

db.Persons.TypeOf<Person>().First();

Upvotes: 1

Related Questions