EF 5 Code First:两个实体之间的一对一和一对多关联

问题描述:

我有两个实体:人员和公司。一个公司有一个或多个联系人(人)。一家公司至少有一个主要联系人(人)。什么是实施这个最好的方法?EF 5 Code First:两个实体之间的一对一和一对多关联

enter image description here

这里是实体:

public class Person 
{ 
    public int PersonId { get; set; } 
    public string PersonName { get; set; } 
} 
public class Company 
{ 
    public int CompanyId { get; set; } 
    public string CompanyName { get; set; } 
    public virtual ICollection<Person> Contacts { get; set; } 
    public int PrimaryContactId { get; set; } 
    [ForeignKey("PrimaryContactId")] 
    public virtual Person PrimaryConctact { get; set; } 
} 

上下文和初始化器:

public class TolleContext : DbContext 
{ 
    public DbSet<Company> Companies { get; set; } 
    public DbSet<Person> Persons { get; set; } 
    public TolleContext() 
    { 
     Database.SetInitializer(new TolleContextInitializer()); 
    } 
} 
public class TolleContextInitializer : DropCreateDatabaseAlways<TolleContext> 
{ 
    protected override void Seed(TolleContext context) 
    { 
     var p1 = context.Persons.Add(new Person { PersonName = "Anatoly" }); 
     var p2 = context.Persons.Add(new Person { PersonName = "Johannes" }); 
     var contacts = new List<Person> {p1, p2}; 
     var company = new Company 
      { 
       CompanyName = "Bool", 
       PrimaryConctact = p1, 
       Contacts = contacts 
      }; 
     context.Companies.Add(company); 
     context.SaveChanges(); 

     base.Seed(context); 
    } 
} 

如果我一个人作为一个PrimaryContact的公司联系起来,它不出现在company.Contacts。当我一个人作为主要联系人相关联,并加入到为同一家公司的联系人列表,它抛出一个错误:

Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.

我希望有关实现这样的场景可能的方式回答。

+0

您的类图有点误导,您有'Company.Contacts',但您的关系线表示它是1对1的关系。一家公司只能有一个联系人和一个主要联系人? – CodingGorilla 2013-02-08 16:25:36

+0

为什么你将PrimaryContact分离出来而不是Person上的字段? – IronMan84 2013-02-08 16:43:54

+0

谢谢@CodingGorilla和IronMan84我已经更新了类图。我将尝试将PrimaryContact关联作为Person上的字段。 – 2013-02-08 17:00:23

显然Person不能属于多个公司。所以你可以让Primary属性为Person。它降低了模型复杂性:您只需要一对多关联。然而,这增加了业务逻辑的复杂性:(1)你需要获得通过

company.Persons.Where(p => p.IsPrimary).First(); 

主要联系人这是不一样阅读导航属性一样容易,和(2),你需要的逻辑,以确保只有一个Person是主要的。

如果要保留当前模型,应先保存公司及其联系人,然后在第二个事务中分配主要联系人。当你在一个事务中执行它时,EF可以同时设置两个生成的外键。它必须首先为公司的FK创建公司,并首先为公司的FK创建公司。

+0

谢谢!听起来不错。我现在正在设计我的模型,所以我不会被迫保留我的模型。如果我遵循您的建议并创建IsPrimary属性,那么确保公司每次只有一个主要联系人的最佳方法是什么?我感谢你的回答! – 2013-02-09 14:05:10

+0

只是“蛮力”:做一个主要的,并检查其他人是否。 – 2013-02-09 15:11:17

+0

谢谢你的帮助。它必须是首先在EF代码中实现此功能的最佳方法。 – 2013-02-16 14:02:24