EF 6:映射复杂类型集合



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

例如,假设您有一个名为Student的实体,它有一组联系人。对于NH,我可以简单地说Student有一个联系人集合,联系人是一个组件(相当于ef中的复杂类型)。EF是否可以在不更改与实体的联系方式的情况下实现这一点?

只需为复杂类型中的每个属性添加一列,即可将复杂类型映射到实体的表。因此,将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;}
}

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

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

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

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

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

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

最新更新