代码之家  ›  专栏  ›  技术社区  ›  J. Michiels

实体框架:使用多个连接表

  •  2
  • J. Michiels  · 技术社区  · 7 年前

    我设计了一个数据库,非常注重规范化。 这里有一段: https://i.stack.imgur.com/1Vbiw.png

    首先,如果你发现这个设计有任何问题,请随时告诉我。

    目标是建立公司,每个公司都有一些部门。 部门可以在公司之间共享。 如下所示: Company 1 可以有 Department 1, 2 and 3. Company 2 可以有 Department 1, 5, 8 and 9.

    这个 BusinessUnits 将有权访问 departments . 但这取决于 department 已链接。

    BusinessUnit 1 可能有访问权限 Department 1 属于 公司1 ,但应无法访问 部门1 属于 公司2 .

    这个 CompanyDepartment 配置表非常明显。 它将公司与(可能)多个部门联系起来。

    这个 CompanyDepartmentBusinessUnit 配置表用于链接 业务单位 Departments Company . 在此表中 CompanyId DepartmentId 将复合外键构成的主键 公司部门 (即: 公司ID 部门ID 以及)。

    我在实体框架中使用数据库优先的方法。 对于简单连接表,我覆盖了 OnModelCreating my中的方法 DbContext .

    我是如何做到这一点的:

    https://i.stack.imgur.com/5V8Uf.png

    我现在的问题是:如何为 公司部门业务单元 关系

    假设我的用户选择查看 公司1 . 我想过滤所有 部门 链接到的 公司1 但对于 BusinessUnit 用户所在的位置(例如 Business Unit 2 ).

    提前感谢您,祝您假期愉快!

    1 回复  |  直到 6 年前
        1
  •  2
  •   Ivan Stoev    7 年前

    只有在以下情况下,EF才允许您使用隐式连接表:(1)它没有其他列;(2)它没有被其他实体引用,而不是被多对多关系的两端引用。

    CompanyDepartment 满足条件(1),但不满足条件(2),因为它引用自 CompanyDepartmentBusinessUnit ,因此需要使用具有两个一对多关系的explcit实体。

    一旦你这样做了,现在就可以看到 公司部门业务单元 满足这两个条件,因此可以使用隐式连接表建模 BusinessUnit 公司部门 .

    话虽如此,最终的模型应该是这样的:

    public class Company
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<CompanyDepartment> DepartmentLinks { get; set; }
    }
    
    public class Department
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<CompanyDepartment> CompanyLinks { get; set; }
    }
    
    public class BusinessUnit
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsPersonal { get; set; }
        public ICollection<CompanyDepartment> CompanyDepartments { get; set; }
    }
    
    public class CompanyDepartment
    {
        public int CompanyId { get; set; }
        public int DepartmentId { get; set; }
        public Company Company { get; set; }
        public Department Department { get; set; }
        public ICollection<BusinessUnit> BusinessUnits { get; set; }
    }
    

    并考虑到默认EF约定,使用以下最小fluent配置:

    modelBuilder.Entity<Company>().ToTable("Company");
    modelBuilder.Entity<Department>().ToTable("Department");
    modelBuilder.Entity<BusinessUnit>().ToTable("BusinessUnit");
    modelBuilder.Entity<CompanyDepartment>().ToTable("CompanyDepartment");
    
    modelBuilder.Entity<CompanyDepartment>()                
        .HasKey(e => new { e.CompanyId, e.DepartmentId });
    
    modelBuilder.Entity<CompanyDepartment>()
        .HasMany(e => e.BusinessUnits)
        .WithMany(e => e.CompanyDepartments)
        .Map(m => m
            .MapLeftKey("CompanyId", "DepartmentId")
            .MapRightKey("BusinessUnitId")
            .ToTable("CompanyDepartmentBusinessUnit")
        );