2012-03-25 102 views
1

这是我的第一个问题,我希望不是一个愚蠢的人。一对多关系流利API编码First

我有以下实体这里

客户 公司 电话

public class Customers 
{ 
    public Customers() 
    { 
     Phones = new List<Phones>(); 
    } 

    public Guid Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public ICollection<Phones> Phones { get; set; } 
} 
public class Phones 
{ 
    public Guid Id { get; set; } 
    public string Number { get; set; } 
    public string Extension { get; set; } 

} 

public class Companies 
{ 
    public Companies() 
    { 
     Phones = new List<Phones>(); 
    } 

    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public ICollection<Phones> Phones { get; set; }   
} 

我想用流利的API,一个以手机之间一对多的关系,并与公司和手机相同的创建。

+4

只有查克诺里斯能够掌握relanshioshio。 – Slauma 2012-03-25 15:29:20

+0

抱歉,错字,请有效的评论,这会浪费我的时间。 – 2012-03-25 18:56:05

+0

对不起,我无法抗拒:)这看起来不像是一个错字,而是一个巨大的错字集群。你可以回滚编辑?第一个版本更有趣。我现在提供了一个答案。 – Slauma 2012-03-25 19:37:17

回答

6

我不知道,如果你想以下几点:

modelBuilder.Entity<Customers>() 
    .HasMany(c => c.Phones) 
    .WithOptional() 
    .Map(m => m.MapKey("CustomerPhoneId")); 

modelBuilder.Entity<Companies>() 
    .HasMany(c => c.Phones) 
    .WithOptional() 
    .Map(m => m.MapKey("CompanyPhoneId")); 

使用MapKey是可选的。它只是给外键列一个你想要的名字。如果您省略此EF将创建一个标准名称(与下划线:..._Id)。

事实上,整个映射是可选的,因为映射约定只会在没有任何Fluent API映射的情况下创建相同的关系。

Phones表将有两个空的外键CustomerPhoneId分别CompanyPhoneId指的Customers表和Companies表。

编辑

一种替代这将只需要在Phone表针对多个不同实体一个外键将是一个继承映射:

public abstract class OrganizationsWithPhone 
{ 
    public OrganizationsWithPhone() 
    { 
     Phones = new List<Phones>(); 
    } 

    public Guid Id { get; set; } 
    public ICollection<Phones> Phones { get; set; } 
} 

public class Customers : OrganizationsWithPhone 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

public class Companies : OrganizationsWithPhone 
{ 
    public string Name { get; set; } 
} 

public class Phones 
{ 
    public Guid Id { get; set; } 
    public string Number { get; set; } 
    public string Extension { get; set; } 
} 

映射:

modelBuilder.Entity<OrganizationsWithPhone>() 
    .HasMany(o => o.Phones) 
    .WithOptional() // or .WithRequired() 
    .Map(m => m.MapKey("OrganizationsWithPhoneId")); 

modelBuilder.Entity<OrganizationsWithPhone>() 
    .ToTable("OrganizationsWithPhone"); 

modelBuilder.Entity<Customers>() 
    .ToTable("Customers"); 

modelBuilder.Entity<Companies>() 
    .ToTable("Companies"); 

现在你只有一个Phones和ba之间的外键关系se表OrganizationsWithPhone,但由于继承映射关系,在派生实体CustomersCompanies的基表和表格之间存在额外的一对一关系。基本上,必要关系的数量保持不变(或者在此模型中甚至更多)。

在这种模式下,客户和公司不能共享相同的电话号码,因为Phones表中的一行指的是OrganizationsWithPhone,它既可以是客户也可以是公司,但不能同时存在。

基表OrganizationsWithPhone只有一列Id。如果您在所有派生实体中具有更多通用属性,则可以将它们移动到基本实体中。

+0

我不喜欢这个方法,如果我有任何其他需要手机的实体,它需要另一个列。 – 2012-03-26 22:54:59

+0

@Son_of_Sam:看到我的编辑,有一个替代解决方案。 – Slauma 2012-03-26 23:41:35

1

你需要的是我称之为关联表,你需要让EF创建一个单独的表来保存关系细节。我不知道EF是否能够做到这一点。但是如果你可以改变你的对象模型,那么一种解决方案就是为这些表指定特定的类型。

public class CustomerPhone 
{ 
    public int Id { get; set; } 
    public Customers Customer { get; set; } 
    public Phones Phone { get; set; } 
} 
public class CompanyPhone 
{ 
    public int Id { get; set; } 
    public Companies Company { get; set; } 
    public Phones Phone { get; set; } 
} 

现在这个班可容纳的关系,所以现在你可以用它们代替电话:

public class Customers 
{ 
    public Customers() 
    { 
     Phones = new List<CustomerPhone>(); 
    } 

    public Guid Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public ICollection<CustomerPhone> Phones { get; set; } 
} 
public class Companies 
{ 
    public Companies() 
    { 
     Phones = new List<CompanyPhone>(); 
    } 

    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public ICollection<CompanyPhone> Phones { get; set; } 
} 

这种方式,你有机会更详细信息添加到您的关系,就像创建日期等。