实体框架CTP5代码优先:使用另一个类的多个集合映射一个类

时间:2011-02-21 15:20:16

标签: .net entity-framework code-first entity-framework-ctp5 ef-code-first

使用EF CTP5 Code-First我试图在一个指向另一个类的类中映射一个包含多个集合的类模型。这是我的意思的一个例子:

public class Company
{
    public int CompanyId { get; set; }
    public IList<Person> FemaleEmployees { get; set; }
    public IList<Person> MaleEmployees { get; set; }
}

public class Person
{
    public int PersonId { get; set; }
    public Company Company { get; set; }
}

如果我使用DbContext从此模型创建数据库而无需进一步自定义,如下所示:

public class MyContext : DbContext
{
    public DbSet<Company> Companies { get; set; }
    public DbSet<Person> People { get; set; }
}

...然后我在SQL Server中得到两个表,一个只有Companies列的简单CompanyId表和一个带有以下列的People表(“FKRN”表示“ “外键关系名称”,由SQL在SQL Server中创建的:

PersonId            int     not nullable
CompanyCompanyId    int     nullable       FKRN: Company_FemaleEmployees
CompanyCompanyId1   int     nullable       FKRN: Company_MaleEmployees
CompanyCompanyId2   int     nullable       FKRN: Person_Company

最后三列与CompanyId表的主键Companies具有所有外键关系。

现在我有几个问题:

  • 1)为什么我在People表中获得三个外键列?我其实期待两个。如果我从public Company Company { get; set; }移除了Person属性,则第三列CompanyCompanyId2消失但我也失去了该类中的引用属性。

  • 2)假设我从Company表中删除Person属性(我的模型中并不需要它)。有没有办法给剩下的两个外键列另一个名称,而不是自动创建的CompanyCompanyIdCompanyCompanyId1? (例如FCompanyIdMCompanyId表示与FemaleEmployeesMaleEmployees集合的关系。)

  • 3)有没有办法在CompanyId表中只用一个外键People来定义这个模型?当然,我需要Person类中的差异化附加列(如bool IsFemale)。 Person是FemaleEmployeesMaleEmployees集合的一部分,从不在两者中(在本例中很自然),因此对于SQL,我可以通过WHERE IsFemale = true/false AND CompanyId = 1之类的东西来获取这些集合。我想知道我是否可以给EntityFramework提示以这种方式加载这两个集合。 (这里我想避免通过FemalePersonMalePerson类来扩展模型,这两个类都从Person派生为基类,然后使用例如Table-Per-Hierarchy映射,因为这些派生类将是空的和人为的,除了启用映射到SQL Server之外没有其他目的。)只有一个外键CompanyId允许我将它non-nullable设为{{1}}这是不可能的外键(在同一行中永远不能为空)。

提前感谢您的反馈和建议!

2 个答案:

答案 0 :(得分:3)

  • 问题(1):EF无法将班级Company中的单个参考媒体资源Person映射到班级{中的两个不同的收集端点FemaleEmployeesMaleEmployees {1}}同时。映射约定假设Company中实际存在第三个端点,该端点未在模型中公开。因此创建了第三个外键。

  • 问题(2):使用EF 4.1 Release Candidate,现在可以使用{在Fluent API中指定外键的数据库列名称(使用EF CTP5无法实现)。 {1}}类的{1}}方法:

    Company
  • 提问(3):我仍然不知道。

修改

现在关闭这个旧问题:(3)(将一个实体中的两个导航属性与另一个实体的同一个端点相关联)是不可能的,例如:Specific Entity Framework Code First Many to 2 Model Mapping ...(我记得很多其他问题正在为这种情况寻找解决方案而没有成功)

答案 1 :(得分:2)

我认为你可以这样做:

public class Company
{
    public int CompanyId { get; set; }
    public ICollection<Person> Employees { get; set; }
    public IEnumerable<Person> MaleEmployees {
        get
        {
            Employees.Where(x=> !x.IsFemale);
        }
    }
}

public class Person
{
    public int PersonId { get; set; }
    public Company Company { get; set; }
}

您在人员表中只有一个CompanyID FK。

您可以使用EF上下文加载Male Employees:

context.Entry(companyInstance)
    .Collection(p => p.Employees)
    .Query()
    .Where(u => !u.IsFemale)
    .Load();

我认为你的方法不太好,因为当我向Company.FemaleEmployees添加一名男性时会发生什么? EF不知道这个规则