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

C# 将EF查询限制为具有TPT继承的基类型,c#,.net,linq,entity-framework,linq-to-entities,C#,.net,Linq,Entity Framework,Linq To Entities,考虑以下带有TPT继承的实体框架模型 数据库表: Person (PersonID, Name) Student (PersonID, Grade) EF实体: Person (PersonID, Name) Student (Grade) : inherits from Person 现在,当您试图从数据库中选择person条目时,它将返回Student type var person = db.Persons.First(); // person here is of type Stud

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

数据库表:

Person (PersonID, Name)
Student (PersonID, Grade)
EF实体:

Person (PersonID, Name)
Student (Grade) : inherits from Person
现在,当您试图从数据库中选择person条目时,它将返回Student type

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表中选择数据?

例如,可以通过以下查询完成:

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

尝试使用此代码

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

如果您使用一个
人的列表,并在列表中存储一个
学生
,当您第一次调用
时会收到什么?您将收到一个
Student
实例,因为面向对象代码就是这样工作的
Student
是一个
Person
但如果不创建一个新实例并从原始
Student
实例复制数据,您永远不会得到一个
Person
实例

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

如果在LINQtoEntities中使用第二个示例,则该示例根本不起作用,因为您正在查询中创建实体的实例,这是不允许的。不得对映射的实体进行投影,因为这可能会破坏数据一致性


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

不,这种方法只是在两个现有SELECT周围添加一个SELECT包装器,并且仍然从两个db表中获取数据
person
变量的类型为
Student
。我添加了新的语法。此语法也无法解决此问题
db.Persons.First()
db.Persons.OfType().First()
生成相同的查询和返回值。您的问题很抱歉,但您的问题是:如何强制此查询只选择persondb表中的数据,而不同时选择Persons和Student db表中的数据?我不同意这样的问题,请尝试澄清!非常感谢。假设我有一个
文档
基类,而我的其他一些类继承了它,并且有一些复杂的关系,那么如果我只想获取基类字段(用于显示
文档
的基本属性,即
文档所有者
文档创建日期
,…),该怎么办
EF
生成一个非常复杂的sql,这会降低性能。@马苏德:必须使用投影。