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

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

考虑以下具有 TPT 继承的 Entity Framework 模型。

数据库表:

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

EF 实体:

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

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

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 数据库表中的数据而不是 Person 和 Student 数据库表中的数据?

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

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

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

最佳答案

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

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

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

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

关于c# - 将 EF 查询限制为具有 TPT 继承的基类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12187259/

相关文章:

c# - 访问内部 API Controller

.net - 最小 MINIDUMP_TYPE 设置为转储托管 .net 组件的 native C++ 进程是什么,以便能够在 windbg 中使用 !clrstack

c# - C#中如何从数组中获取随机值

.net - 使用 System.Linq.Expressions API 在 LINQ 中选择列

c# - 如何验证/检查图像是否已存在于数据库中?

c# - 使用 Graph API 登录 Azure B2C

c# - 在datagridview c#的两行之间添加一个新行

c# - 获取 Windows 版本

c# - linq distinct 或 group by 多个属性

c# - DevExpress MVC GridView BindToLINQ() 选择了太多数据