值对象没有身份。ORM 需要身份来更新数据库。
如何欺骗ORM?
(将值对象的 Id 标记为内部将不起作用,因为 ORM 存在于不同的程序集中,并且将其移动到同一程序集是不可接受的)。
提前致谢。
值对象没有身份。ORM 需要身份来更新数据库。
如何欺骗ORM?
(将值对象的 Id 标记为内部将不起作用,因为 ORM 存在于不同的程序集中,并且将其移动到同一程序集是不可接受的)。
提前致谢。
当 Eric Evans 谈到“实体有身份,值对象没有”时,他不是在谈论数据库中的 ID 列——他是在谈论身份作为一个概念。
VO 没有概念上的身份。这并不意味着他们不应该有持久性身份。不要让持久性实现影响您对实体与 VO 的理解。
在这里查看我的帖子。
就我对 DDD 的理解而言,值对象只是划分实体的一种方式。如果一个值对象应该与一个 ID 一起存储在数据库中,那么它就不是一个值对象。
例子:
域模型如下所示(C#):
public class Customer : Entity
{
public Guid CustomerID { get; }
public string LastName { get; set; }
public Address HomeAddress { get; set; }
}
public class Address : ValueObject
{
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
}
相应的数据库表看起来像这样(伪 SQL):
CREATE TABLE Customers
(
CustomerID,
LastName,
HomeAddress_Street,
HomeAddress_City,
HomeAddress_ZipCode,
)
要将地址存储在单独的表中,您可以使其成为具有 ID 的实体。
就我个人而言,我在值对象中有 Id 字段 - 我将其视为值对象的另一个属性(例如名称、位置等)。
它可能不是真正的 DDD,但它对我有用。
您有 2 个选项:
对于您的示例,例如:
public class Customer : Entity
{
public Guid CustomerID { get; }
public string LastName { get; set; }
public Address HomeAddress { get; set; }
}
public class Address : ValueObject
{
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
}
选项 1(伪 SQL):
CREATE TABLE Customer (
// aggregate root
customerId int NOT NULL,
lastName VARCHAR(30),
// value object
street VARCHAR(100),
city VARCHAR(50),
zip VARCHAR(10)
CONSTRAINT PK_Customer PRIMARY KEY (customerId)
)
选项 2(伪 SQL):
// aggregate root
CREATE TABLE Customer (
customerId int NOT NULL,
lastName VARCHAR(30)
CONSTRAINT PK_Customer PRIMARY KEY (customerId)
)
// value object
CREATE TABLE Address (
customerId int NOT NULL, // same ID from Customer
street VARCHAR(100),
city VARCHAR(50),
zip VARCHAR(10)
CONSTRAINT PK_Address PRIMARY KEY (customerId)
)
toDomain(sqlResult)
函数来转换你的域对象中的查询结果one-table
默认使用方法前面的答案中提到的用于持久化值对象的所有选项 - 例如将值对象属性扁平化为它们所属的实体表的列,或通过包含数据模型的唯一 ID 将它们持久化在单独的表中 - 都是有效且良好的解释。当然,这些选项通常独立于特定的底层数据库技术而适用,这是一个很大的优势。
但我认为至少值得一提一些其他选项,这些选项在许多情况下已经足够且易于实施:
以 JSON 表示形式存储值对象
当然,这取决于您的技术限制,但现在许多数据库以及 ORM 解决方案甚至提供了对 JSON 表示的内置支持。有些甚至包括搜索选项。如果您不期望有大量的项目,您甚至可以通过将此列表作为对象的 JSON 集合直接保存在实体表中来将此方法用于实体内的值对象列表。
当然,除了 JSON 之外,还支持其他格式(例如纯文本或 XML),但根据我的经验,我发现 JSON 是最舒服的。
使用基于文档的存储解决方案
值得一提的是,选择基于文档的数据库技术(例如MongoDB)还为持久化域模型实体提供了新选项,因为它允许将聚合作为包括其所有子实体和/或值的整个文档持久化对象。
一个 VO 属于一个实体。我们将使用实体的 ID(企业 ID)来跟踪 VO。
一个VO也可能包含其他实体/VO,它只是代表OO,封装。举个例子,ER,1:N,我们可以用Union Table来持久化它。
专注于业务,而不是那些概念。