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

时间:2017-12-22 10:50:43

标签: c# asp.net-mvc entity-framework ef-database-first

我设计了一个数据库,非常注重规范化。 这是一块: 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 Company 1,但无法访问Department 1 Company 2

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

CompanyDepartmentBusinessUnit配置表用于将BusinessUnitsDepartments的{​​{1}}相关联。 在此表格中,CompanyCompanyId形成了DepartmentId主键的复合外键(即:CompanyDepartmentCompanyId)。

我在Entity Framework中使用了Database-First方法。 对于简单的联结表,我已覆盖DepartmentId中的OnModelCreating方法。

我是如何做到这一点的一个例子:

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

我现在的问题是:我如何为DbContext关系执行此操作?

假设我的用户选择查看CompanyDepartmentBusinessUnit的部门。 我想过滤链接到Company 1的所有Departments,但对用户所在的Company 1也是可见的(例如BusinessUnit)。

提前感谢您,享受您的假期!

1 个答案:

答案 0 :(得分:2)

EF仅允许您使用隐式联结表(1)它没有其他列;(2)如果它不被多对多关系的两端不同的其他实体引用。

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

一旦你这样做,可以看出现在CompanyDepartmentBusinessUnit满足两个条件,因此可以使用BusinessUnitCompanyDepartment的隐式联结表进行建模。

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

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约定,使用以下最小流畅配置:

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")
    );