Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Domain driven design DDD实体、值对象和数据库映射和更新。一成不变的矛盾?_Domain Driven Design_Entity_Value Objects - Fatal编程技术网

Domain driven design DDD实体、值对象和数据库映射和更新。一成不变的矛盾?

Domain driven design DDD实体、值对象和数据库映射和更新。一成不变的矛盾?,domain-driven-design,entity,value-objects,Domain Driven Design,Entity,Value Objects,我一直在DDD做一个小项目。我到处都看到值对象是不可变的,因此,不能修改它。只有实体 我将使用每个人都使用的例子。地址。假设地址是客户实体的VO(也是根聚合)。如果用户更新其地址,这在任何购物车场景中都有效,那么我应该怎么做?我必须修改该VO地址,以便将其持久化到数据库中。也就是说,这个VO必须有一个标识,以便我在数据库中识别它。除非NHibernate使用映射来处理它,对吧。林克托斯不是这样的。 或者我想我必须创建一个新的聚合,其中地址是一个实体?然后几乎在我需要地址的地方都有一份地址副本 不

我一直在DDD做一个小项目。我到处都看到值对象是不可变的,因此,不能修改它。只有实体

我将使用每个人都使用的例子。地址。假设地址是客户实体的VO(也是根聚合)。如果用户更新其地址,这在任何购物车场景中都有效,那么我应该怎么做?我必须修改该VO地址,以便将其持久化到数据库中。也就是说,这个VO必须有一个标识,以便我在数据库中识别它。除非NHibernate使用映射来处理它,对吧。林克托斯不是这样的。 或者我想我必须创建一个新的聚合,其中地址是一个实体?然后几乎在我需要地址的地方都有一份地址副本

不过。我仍然无法包装整个实体/VO概念。在我看来,所有在DB上有表示的东西,即使你在模型中将它作为VO使用,它在某种程度上也是一个实体,因为为了持久化它,你需要某种键在数据库中识别它

在一天结束时,所有值对象的数据都来自数据库(大部分)。所以我仍然不明白,在数据更新的情况下,如何使它们保持不变

经过两个月的紧张阅读,我发现整个DDD是一个巨大的矛盾问题。读了所有这些博客,你就会明白我在说什么。不幸的是,没有任何演示应用程序可以用作角色模型或指导。它们几乎都受到开发人员偏好的影响。然后他们就互相攻击对方的博客。一夜之间DDD大师的博客真的帮助了整个社区的混乱


谢谢你过来。期待有建设性的讨论。

事实上,从Java开始,在您想象的每一种技术中都有大量的演示。此示例到.NET的端口至少有两个:和

至于VO和持久性,如果您认为VO是一个对象,它从一个表示实体的表中包装了几列,那么这就很容易了(例如,Money VO包装amount和currency)。当您希望在SQL级别规范化数据并为VO创建一个表(而不是将它们嵌入实体表)时,问题就开始了。我不知道该问题的好解决方案,但幸运的是,在使用关系存储实现DDD时,这不是一个好的做法。为什么?最重要的原则之一是,骨料应尽可能相互独立。在对象模型中共享VO符合此规则,但在数据存储中共享VO则不符合此规则,例如,此单个表可能会成为锁定瓶颈


简单地说,当使用SQL数据库来存储域模型时,不要考虑在集合之间建立模型。

< P>我相信您的困惑在于数据库行标识与DDD中实体相关的身份概念之间的人工耦合。它们当然是相关的,因为一个实体在数据库中将有一个对应的标识作为标识列表示。然而,仅仅因为某个对象具有作为数据库行的标识,并不意味着该对象具有DDD意义上的标识

在地址示例中,包含地址VO的值通常存储在与客户实体相同的行中。这样,地址就是一个值对象,因为它不存储在自己的行中,也没有标识。更新地址时,会更改客户实体上address属性的值,这反过来会反映在数据库行中


在某些情况下,值对象将存储在其自己的行中。例如,在常规销售订单模型中,订单是一个实体(聚合根),行项目是值对象。虽然行项目是VO,但在关系模型中,它们存储在自己的表中,很可能有主键。然而,在域模型中,VO与订单实体绑定,在该实体之外没有标识。

您也可以尝试从现实世界(或域)的角度来看待此类问题。地址很少改变。更常见的情况是,客户更改了地址(例如,他要搬到另一个公寓),而地址本身也发生了更改


记住这一点,地址必须是一个值对象。

嘿,我知道这是一个非常古老的问题,但我正在进行DDD搜索,并且有一些类似的查询

我用DDD找到的解决方案的最佳途径是忘记DB,考虑模型。所以在上面的情况下,你有一个客户和一个地址VO,你想要一个客户的地址列表,比如在一个电子商务站点中,客户有多个送货地址可供选择。在域模型的真实上下文中,这些地址不仅仅是地址VO,它们是CustomerShippingAddress实体

因此,CustomerShippingAddress实体有一个标识,它有一个地址VO。也许它还有一些其他的东西,比如IsDefault,DateAdded等等

我建议您只能从传入地址VO的客户实体实例化CustomerShippingAddress,然后返回CustomerShippingAddress的聚合根,该根包含对客户的ID引用

这样可以维护AddressVO,但可以在多个场景中重用该VO

当客户选择一个地址作为订单的发货地址时,他们选择的地址VO将应用于订单聚合。这意味着该订单上的发货地址将及时锁定到当时的地址VO。CustomerShippingAddress可能会被修改