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

EF 6: mapping complex type collection?

EF 6(代码优先)是否支持复杂类型集合(值对象集合)映射?我知道它支持复杂类型,但还没有找到我们拥有复杂类型集合的示例。

例如,假设您有一个名为 Student 的实体,其中包含一组联系人。对于 NH,我可以简单地说 Student 有一个联系人集合,并且该联系人是一个组件(相当于 ef 中的复杂类型)。可以在不更改与实体的联系的情况下使用 EF 完成此操作吗?

复杂类型映射到实体的 table,只需为复杂类型中的每个 属性 添加一列。因此,将联系人作为一个单独的实体:

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 table 的映射:

ID
PrimaryContact_Address
PrimaryContact_PhoneNumber
PrimaryContact_Email
SecondaryContact_Address
SecondaryContact_PhoneNumber
SecondaryContact_Email

复杂类型只是 shorthand 用于在您需要的任何地方声明相同的成员。您可以在一堆需要联系人数据的其他实体中使用相同的联系人类型,而不必为每个实体显式定义 AddressPhoneNumberEmail 属性。所以你不能真正在集合中使用它们,因为每次你想向它添加或删除项目时,你都必须从 table 本身添加或删除列。

public class Student
{
    [Key]
    public int ID {get; set;}
    public ICollection<Contact> 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 class 中删除 ComplexType 即可干净地使用集合。这将在数​​据库中创建一个 table,但是:

public class Student
{
    [Key]
    public int ID {get; set;}
    public ICollection<Contact> 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;}
}

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

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

我知道的唯一解决方法是将值 object/collection 表示以某种序列化格式((例如 XML、JSON、二进制等)映射到单个数据库 string/binary 列。虽然这适用于 reading/storing 数据,但它缺乏查询功能,因此 IMO 不是一个严肃的选择。

谈到 EF6,我认为它永远不会获得支持。 EF6 基本上处于维护模式并且 won't get future major improvements.

EF Core 在这方面看起来更有前途,因为对拥有实体集合的支持 scheduled for the next EF 2.2 release。然而,他们将如何实现它们(最初)是未知的,并且考虑到他们如何实现 拥有的类型 ,这可能不是你期望的方式,所以不能在如果它们适用于值对象收集方案,请提前。

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