一对多关系Fluent API Code First

时间:2012-03-25 14:41:31

标签: entity-framework-4.1

这是我的第一个问题,我希望不是一个愚蠢的问题。

我这里有以下实体

客户 公司 电话

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创建手机之间的一对多关系,与公司和手机相同。

3 个答案:

答案 0 :(得分: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表将有两个可以为空的外键CustomerPhoneIdCompanyPhoneId分别引用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和基表OrganizationsWithPhone之间只有一个外键关系,但由于继承映射,基表和表之间存在额外的一对一关系派生实体CustomersCompanies。基本上,必要关系的数量保持不变(或者在此模型中甚至还有一个)。

在此模型中,客户和公司不能共享相同的电话号码,因为Phones表中的一行指的是OrganizationsWithPhone,可以是客户或公司,但不能同时是同一时间。

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

答案 1 :(得分: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; }
}

现在这些类可以保持这种关系,所以现在你可以用它们替换Phone:

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; }
}

通过这种方式,您可以为您的关系添加更多详细信息,例如创建日期等。

答案 2 :(得分:0)

参见本教程 - 教师与部门之间,课程与入学之间以及学生与入学之间有一对多的关系,您可以将其用作模型:

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application