2012-04-10 73 views
0

我正在使用SQL数据库(对它仍然相当新),并且试图创建“one-to-one”或子表超级关系。我正在使用C#和LINQ-to-Entities。LINQ选择New以从超类型子类型关系中创建一个表

作为一个常见的例子,我有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 

不幸的是,它不feasibe做选择新{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到相同的表型。

谢谢,

回答

0

你正在努力与modelliing继承。 StudentTeacher都是Person s。有多种方法可以将关联数据库中的继承类存储,实体框架支持这些关联数据库。

可能最能帮助你的方法叫做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

+0

这对我有意义。在我的情况下,人与其他表有很多关系,并有5个子类型。在TPC中,我将每个5个子表连接到Person的每个连接表?链接太棒了! – Sethery 2012-04-16 16:12:46

+0

是的,这就是你通常用的子类型。我必须说分类是很棒的,但很多人(包括我)赞成“构图而非继承”。如果你在谷歌上,你会被链接充斥。从GoF家伙开始,着名的设计模式创始人。 – 2012-04-16 20:09:23