使用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
属性(我的模型中并不需要它)。有没有办法给剩下的两个外键列另一个名称,而不是自动创建的CompanyCompanyId
和CompanyCompanyId1
? (例如FCompanyId
和MCompanyId
表示与FemaleEmployees
和MaleEmployees
集合的关系。)
3)有没有办法在CompanyId
表中只用一个外键People
来定义这个模型?当然,我需要Person
类中的差异化附加列(如bool IsFemale
)。 Person是FemaleEmployees
或MaleEmployees
集合的一部分,从不在两者中(在本例中很自然),因此对于SQL,我可以通过WHERE IsFemale = true/false AND CompanyId = 1
之类的东西来获取这些集合。我想知道我是否可以给EntityFramework提示以这种方式加载这两个集合。 (这里我想避免通过FemalePerson
和MalePerson
类来扩展模型,这两个类都从Person
派生为基类,然后使用例如Table-Per-Hierarchy映射,因为这些派生类将是空的和人为的,除了启用映射到SQL Server之外没有其他目的。)只有一个外键CompanyId
允许我将它non-nullable
设为{{1}}这是不可能的外键(在同一行中永远不能为空)。
提前感谢您的反馈和建议!
答案 0 :(得分:3)
问题(1):EF无法将班级Company
中的单个参考媒体资源Person
映射到班级{中的两个不同的收集端点FemaleEmployees
和MaleEmployees
{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不知道这个规则