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

问题描述 投票:5回答:2

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

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

c# entity-framework domain-driven-design complextype value-objects
2个回答
1
投票

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

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

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

谈到EF6,我认为它不会得到那种支持。 EF6基本上处于维护模式和won't get future major improvements

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

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


3
投票

通过为复杂类型中的每个属性添加一列,复杂类型将映射到实体的表。因此,将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<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类中删除ComplexType,即可干净地使用集合。这会在数据库中创建一个表,但是:

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;}
}
© www.soinside.com 2019 - 2024. All rights reserved.