将EF查询限制为具有TPT继承的基本类型

时间:2012-08-29 22:14:03

标签: c# .net linq entity-framework linq-to-entities

考虑以下具有TPT继承的实体框架模型。

数据库表:

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

EF实体:

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

现在,当您尝试从数据库中选择人员条目时,它将返回学生类型。

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

如何强制此查询只选择Person db表中的数据而不是Person和Student数据库表中的数据?

例如,可以使用以下查询完成:

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

但它看起来很蹩脚,在现有查询上生成一个额外的SELECT语句,这样返回的人实体对象将不会被EF上下文跟踪。所以,我想知道为什么db.Persons.First()会返回Student个对象?这不是违反直觉的吗?

2 个答案:

答案 0 :(得分:2)

如果您使用Person列表并将单个Student存储到列表中,则在致电First时会收到什么?您将收到一个Student实例,因为这是面向对象的代码应该如何工作StudentPerson但是如果不创建新实例,您将永远不会获得Person实例并从原始Student实例复制数据。

EF以相同的方式工作 - 实体是原子的。它跨越了多少个表并不重要。如果查询继承层次结构,您将始终获得正确类型的整个实例,因为这是面向对象的代码应该如何工作的。

如果在Linq-to-entities中使用,那么您的第二个示例根本不起作用,因为您正在查询中创建实体的实例 - 这是不允许的。不得对映射实体进行预测,因为它可能会破坏数据的一致性。

方法是将投影用于非实体类型 - 自定义未映射类或匿名类型。

答案 1 :(得分:1)

尝试使用此代码

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