0

我正在使用一个 SQL 数据库(对它来说还是相当新的),并试图创建“一对一”或子表超表关系。我正在使用 C# 和 LINQ-to-Entities。

作为一个常见的例子,我有 3 个表。

Person:
PersonId, Age, p1, p2, ..., pn

Student:
PersonId, Grade, GPA, s1, s2, ...., sn

Teacher:
PersonId, PrimarySubject, YearsAtSchool, IsCoach, ....

我希望能够做的是基于 Person 的查询,然后获取相关的子类型数据。我有 relevatn TypeId 表来确保关系。

假设我查询了一个人并且他们是学生,那么我想得到:

QueriedResult
PersonId, Age, p1, ..., pn, Grade, GPA, s1, ..., Sn 

不幸的是,选择新的 {p.PersonID, etc} 是不可行的,因为在我的情况下子表和元素太多。

每当我使用我的代码时,我都会得到两个单独的表的 IEnumerable。我提供的示例代码在没有关联学生时返回空值,如果此人是学生,则在第二列中返回一个表。

var query = (from p in Persons.AsEnumerable()
join s in Students on p.PersonId equals s.PersonId
select new {p, s});

尽管所有建议的方法似乎都要求 p & s 是相同的表类型,但我听说过很多关于“扁平化”的讨论。

谢谢,

4

1 回答 1

0

您正在为建模继承而苦苦挣扎。Student两者Teacher都是Persons。有几种方法可以将继承的类存储在关系数据库中,实体框架支持这些方法。

可能对您最有帮助的方法称为按具体类型表 (TPC),这意味着每种类型在数据库中都有自己的表,而 EF 负责将子类型存储在正确的表中。该链接还提到了另外两种常用方法(TPH 和 TPT)。如果您的子类有相对多的共同点,TPT 也可能是合适的。

所以你会有

abstract class Person { PersonId, ... }

class Student : Person { Grade, ... }

class Teacher: Person { PrimarySubject, ... }

如果你想要Student你做

context.Persons.OfType<Student>().Where(....

这会为您提供QueriedResult预期的结果。

注意Person是抽象的。如果你想让它具体化,你最好创建一个抽象PersonBase类(或类似的)并Person从它派生,就像Studentand一样Teacher

于 2012-04-13T23:09:13.017 回答