LINQ选择“新建”以从超类型子类型关系创建一个表

时间:2012-04-10 18:33:06

标签: c# join linq-to-entities relational-database

我正在使用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的查询,然后获取相关的子类型数据。我有相关的TypeId表来确保关系。

如果我询问了一个人并且他们是学生,那么我想得到:

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

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

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

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

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

谢谢,

1 个答案:

答案 0 :(得分:0)

你正在努力进行模仿继承。 StudentTeacher都是Person。有几种方法可以在关系数据库中存储继承的类,实体框架支持这些。

可能对您有所帮助的方法称为Table per Concrete Type (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,就像StudentTeacher一样。