实体框架代码单个表中的多对多关系

时间:2013-03-24 14:42:43

标签: c# entity-framework many-to-many code-first

我已经潜伏了很长一段时间,所以这是第一个问题;)

我一直在玩Entity Framework 5.0 Code First,我想做以下事情:

我有两个实体,我希望每个实体都以下列方式与Address实体建立关系:

  • 我有一个存储地址值的地址实体,它与有值的实体没有关系,而是
  • 还有另一个实体 AddressBook ,它引用了地址实体和相应的实体(公司,未来的其他一些人)

这是代码:

public partial class Address : BaseEntity
{
    [Key]
    public int ID { get; set; }
    public string Street { get; set; }
    public string CityName { get; set; }
    public int? PostalCode { get; set; }

    public virtual ICollection<Person> Persons { get; set; }
    public virtual ICollection<Company> Companies{ get; set; }
}

public partial class Person : BaseEntity 
{
    [Key]
    public int ID { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }

}

public partial class Company: BaseEntity 
{
    [Key]
    public int ID { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }
}

这样做是用表创建数据库模式:

  • 地址
  • AddressPerson(带复合主键)
    • ADDRESS_ID
    • PERSON_ID
  • AddressCompany
    • ADDRESS_ID
    • COMPANY_ID
  • 公司

这就是我想要做的事情:

  • 地址
  • 地址簿
    • Address_ID(PK)
    • Person_ID(FK)
    • Company_ID(FK)
  • 公司

我想要的是像 AddressBook

这样的表格
public partial class AddressBook
{
    [Key]
    public int ID { get; set; }
    public virtual Address Address { get; set; }
    public virtual Person Person { get; set; }
    public virtual Company Company { get; set; }
}

我不确定如何在公司类中定义导航属性。

他们应该拥有ICollection<Address> Addresses导航属性,因为我希望他们只使用地址集合而不了解基础 AddressBook

是否可以使用DbModelBuilder执行此操作,还是应该在getter属性的setterICollection<Address> Addresses内编写代码,并从 AddressBook

谢谢!

1 个答案:

答案 0 :(得分:0)

您无法以实体框架将AddressesPerson中的Company集合理解为真正的导航属性(支持急切和延迟加载等)的方式创建映射。为此,您确实需要AddressBooks个集合。您可以将Addresses添加为非映射和只读辅助属性,然后:

public partial class Person : BaseEntity 
{
    [Key]
    public int ID { get; set; }
    public virtual ICollection<AddressBook> AddressBookEntries { get; set; }

    public IEnumerable<Address> Addresses
    {
        get { return AddressBookEntries.Select(ab => ab.Address); }
    }
}

(与Company相同。)

另一种选择,在我看来更好的方法是为PersonCompany创建一个公共基类,将Addresses集合移动到该基类中并且只有一个 - 此基类与Address之间的多对多关系和单个连接表:

public abstract class EntityWithAddresses : BaseEntity
{
    [Key]
    public int ID { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }
}

public partial class Person : EntityWithAddresses 
{
}

public partial class Company : EntityWithAddresses 
{
}

Address有一个新基类的导航集合:

public partial class Address : BaseEntity
{
    [Key]
    public int ID { get; set; }
    public string Street { get; set; }
    public string CityName { get; set; }
    public int? PostalCode { get; set; }

    public virtual ICollection<EntityWithAddresses> EntityWithAddresses { get; set; }
}