EF 6:映射复杂类型集合?

EF 6(代码优先)是否支持复杂类型集合(Value Object集合)映射? 我知道它支持复杂类型,但还没有找到一个我们有一组复杂类型的例子。

例如,假设您有一个名为Student的实体,它有一组联系人。 对于NH,我可以简单地说学生有一组联系人,而联系人是一个组件(相当于ef中的复杂类型)。 这可以通过EF完成而不改变与实体的联系吗?

显然NHibernate在这方面更灵活,因为在编写本文时(EF6.2和EF Core 2.1),EF6和EF Core都不支持复杂(或更普遍的原始或值对象)类型集合映射。

EF Core更糟糕,因为自有实体类型 (据称是EF复杂类型的替代品)实际上具有更多类似于行为的实体(从更改跟踪角度来看)并且不能用作DDD不可变多属性值对象。

我知道的唯一解决方法是将值对象/集合表示以某种序列化格式(例如XML,JSON,二进制等)映射到单个数据库字符串/二进制列。虽然这可用于读取/存储数据,但它缺乏查询function,因此IMO不是一个严肃的选择。

谈到EF6,我认为它不会得到那种支持。 EF6基本上处于维护模式, 不会得到未来的重大改进 。

EF Core在这方面看起来更有前景,因为支持自有实体的集合 计划用于下一个EF 2.2版本 。 然而,不知道他们将如何实现它们(最初),并考虑到它们如何处理所拥有的类型 ,它可能不是您期望的方式,因此如果它们适用于价值对象收集方案,则不能提前说明。

我知道这不是你想要的答案,但那是现实。

只需为复杂类型中的每个属性添加一列,就可以将复杂类型映射到实体的表。 因此,将Contact作为单独的实体:

public class Student { [Key] public int ID {get; set;} public Contact PrimaryContact { get; set; } public Contact SecondaryContact{ get; set; } } [ComplexType] public class Contact { public string Address{get; set;} public string PhoneNumber{get; set;} public string Email{get; set;} } 

将产生具有列的Student表的映射:

 ID PrimaryContact_Address PrimaryContact_PhoneNumber PrimaryContact_Email SecondaryContact_Address SecondaryContact_PhoneNumber SecondaryContact_Email 

复杂类型只是在任何需要的地方声明相同成员的简写。 您可以在需要联系数据的一堆其他实体中使用相同的Contact类型,而无需为每个实体显式定义AddressPhoneNumberEmail属性。 因此,您无法在集合中真正使用它们,因为每次要添加或删除项目时,都必须在表格中添加或删除列。

 public class Student { [Key] public int ID {get; set;} public ICollection Contacts{ get; set; } } [ComplexType] public class Contact { public string Address{get; set;} public string PhoneNumber{get; set;} public string Email{get; set;} } ID Contacts[x]_Address? Contacts[x]_PhoneNumber? Contacts[x]_Email? 

在哪里可以存储联系人项目? 你怎么能索引它? 如果您尝试这样做,映射器将完全忽略Contacts属性。

只需从Contact类中删除ComplexType,即可干净地使用集合。 这会在数据库中创建一个表,但是:

 public class Student { [Key] public int ID {get; set;} public ICollection Contacts{ get; set; } } public class Contact { [Key] public int ID {get; set;} public string Address{get; set;} public string PhoneNumber{get; set;} public string Email{get; set;} }