C# 将EF查询限制为具有TPT继承的基类型
考虑以下带有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
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,这会降低性能。@马苏德:必须使用投影。