【问题标题】:LINQ Select New to create one table from super-type sub-type relationshipLINQ 选择新建从超类型子类型关系创建一个表
【发布时间】:2012-04-10 18:33:05
【问题描述】:

我正在使用一个 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 是相同的表类型。

谢谢,

【问题讨论】:

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


    【解决方案1】:

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

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

    所以你会有

    abstract class Person { PersonId, ... }
    
    class Student : Person { Grade, ... }
    
    class Teacher: Person { PrimarySubject, ... }
    

    如果你想要Students 你可以

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

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

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

    【讨论】:

    • 这对我来说很有意义。在我的例子中,Person 与其他表有很多关系,并且有 5 个子类型。在 TPC 中,我会将 5 个子表中的每一个连接到 Person 的每个连接表吗?链接太棒了!
    • 是的,这就是您通常对子类型所做的事情。我必须说子类型很棒,但是很多人(包括我)更喜欢“组合而不是继承”。如果你用谷歌搜索,你会被链接淹没。从著名的设计模式创始人 GoF 开始。
    猜你喜欢
    • 2014-07-25
    • 2021-09-29
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 2014-05-03
    相关资源
    最近更新 更多