【问题标题】:How does entity framework represend this relationship, one table reference by multiple tables实体框架如何表示这种关系,一个表被多个表引用
【发布时间】:2021-11-04 03:54:41
【问题描述】:

实体框架代码如何首先定义这样的表结构 Structure

class A
{
    PK
    Name1
    List<ClassC>
}

class B
{
    PK
    Name2
    List<ClassC>
}

class C
{
    PK
    ClassA
    ClassB
}

【问题讨论】:

    标签: c# entity-framework ef-code-first


    【解决方案1】:

    您在图表中概述的关系可能不会像您认为的那样发挥作用。

    如果 TableC 上的 ParentId 旨在指向 表 A 上的 Id 或表 B 上的 Id,那将不起作用。匹配的记录必须在表 A 和表 B 中。

    SQL Server 将允许这样做,并且只要在实体中声明 ParentId 并将其设置为两个关系的 FK,EF(至少 EF6)将支持这一点。阴影属性(EF6 使用Map(x =&gt; x.MapKey()))不起作用,因为它希望对两个关系使用相同的名称,至少在 EF6 中是这样。在 EF Core 中,您需要测试这是否受支持。

    举以下两个例子: 我们有一个学校系统,我们有学生(表 A)和教师(表 B)。学生和教师都有一个或多个地址(表 C)

    地址可能属于学生,也可能属于教师,但很少会同时属于学生和教师。因此,像您在 ParentID 之间指定一个 FK 指向 Student 和 Teacher 表的表结构没有多大意义。家长 ID 5 必须同时存在于学生和教师中,而不是其中一个,即使可以,您也不知道地址是指学生还是教师。从数据库的角度来看,您可以添加 ParentType 来指示 ParentId 是指学生还是教师,但您必须删除 ParentId 上的 FK,因为它不能指向两个表并期望只找到一个或另一个。这成为一种隐含的关系,效率不高,不能通过约束来强制执行。 (即确保 ParentId 实际上指向任一表中的一行,或正确的表等。)它也不能映射为 EF 中的关系。

    可行的方法是将 Student 和 Teacher 组合成一个 Person 表,其中包含角色标识符之类的东西,以判断 Person 是 Student 还是 Teacher。这样,地址表就可以合法地拥有一个 PersonId。 (而不是 ParentId)在 EF 中,您仍然可以将 Student 和 Teacher 类都通过 Person 基类映射到 Person 表,使用 Role 作为鉴别器。在 EF 中,这称为 Table-per-Hierarcy 继承。

    这适用于与公共实体(如地址)共享关系的类具有合理相关性的情况。我们可以在基类表和相关的多边表之间建立一对多的关系。如果您希望学生、教师和学校拥有一个或多个地址,则效果不佳。 (即一所学校可以有校园)一所学校不是一个“人”,也不应该被视为一个人。即使对于相关实体,这也可能是有问题的,我们想要几个特定于学生的字段而不是特定于教师的其他字段。这需要向 Person 表添加一组可为空的字段,或者从 Person 到 StudentInfo 或 TeacherInfo 表的 0-1 关系来保存学生或教师的特定详细信息。

    如果我们有不相关的实体并且需要跨诸如 Student 表、Teacher 表和 School 表之类的对象之间的一对多关系,所有这些都与一个或多个 Address 记录相关,那么更好的选择是使用许多多对多关系。

    学生

    StudentAddress (StudentId, AddressId)

    老师

    TeacherAddress (TeacherId, AddressId)

    学校

    SchoolAddress (SchoolId, AddressId)

    地址

    在这种情况下,如果多对多表仅包含作为复合 PK 的 FK 而没有其他列,并且您使用的是 EF6 或 EF,那么学生、教师或学校可以拥有地址实体的集合核心 5。(我相信支持这一点)早期版本的 EF Core 不支持通过未映射的连接表自动引用,因此这需要通过映射的连接实体声明集合。 (即ICollection&lt;StudentAddress&gt;

    地址可以包含对学生/教师/学校集合的引用,但通常我不会费心映射这些,除非它们真的有必要。作为多对多关系,这将合法地允许同一个地址属于多个学生,而这在适当的一对多中是不允许的。

    为了执行正确的一对多,地址表将被删除,地址字段将被放入每个 StudentAddress、TeacherAddress 和 SchoolAddress 表中。

    【讨论】:

      【解决方案2】:

      您当前的班级结构与图片上的 ERD 不一致。
      关系构成图片:
      C 可以连接多个 A,但 A 只能连接一个 C (1:M)
      C 可以连接多个 B,但 B 只能连接一个 C (1:M)
      下面的结构应该可以工作:

      public class A
      {
          public int Id { get; set; }
          public string Name { get; set; }
      
          // Fully defined relationship
          public int C_Id { get; set; }
          public C C_ojb { get; set; }
      }
      
      public class B
      {
          public int Id { get; set; }
          public string Name { get; set; }
      
          // Fully defined relationship
          public int C_Id { get; set; }
          public C C_obj { get; set; }
      }
      
      public class C
      {
          public int Id { get; set; }
          public string Name { get; set; }
      
          // Fully defined relationship
          public List<A> As { get; set; }
          public List<B> Bs { get; set; }
      }
      

      我建议您访问以下页面:
      https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key
      https://www.learnentityframeworkcore.com/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-10
        • 1970-01-01
        相关资源
        最近更新 更多