0

我想用的是吉米·尼尔森在他的书中Applying DDD with Patterns提到的一个想法,那就是,如果我有一个像产品例如,我将一个实体喜欢拍摄该实体的历史信息的快照,类似ProductSnapshot但我想知道我可以如何实现这与一个ORM(我目前正在使用实体框架)。我现在面临的主要问题是,如果我有另一实体像订单行是通过其构造函数接收产品那么实体框架将需要你做的那种类型的公共财产要持续存在,因此这会强迫我有这样的事情:管理实体和其快照与ORM

class OrderLine { 
public Product Original Product {get; set;} 
public ProductSnapshot Snapshot {get; set;} 
} 

,这似乎笨拙,不直观,我不知道如何处理得当,当涉及到数据绑定(对哪些财产我应该绑定)最后我认为产品实体ProductSnapshot值对象加上订单行被接受时,快照只取,之后不需要产品

回答

1

在做DDD时,忘记数据库存在。这意味着ORM也不存在。现在,由于您不必关心持久性和ORM限制,因此可以根据域需求对ProductSnapshot进行建模。

创建一个包含所有必需成员的ProductSnapshot类。该类可能是SnapshotService.GetSnapshot(Product p)的结果。获得ProductSnapshot后,只需将其发送到存储库SnapshotsRepository.Save(快照)即可。作为一个快照,这意味着它可能更多是一个数据结构,一个“愚蠢”的对象。它也应该是不变的,'冻结'。

存储库将使用EF来实际保存数据。你决定EF实体和关系是什么。 ProductSnapshot被持久化视为一个业务对象(实际上它只是一个简单的Dto并不重要),并且EF实体可能看起来非常不同(例如,我将业务对象以序列化形式存储在键 - 价值表)根据您的查询需求。

一旦您定义了EF entites,您需要将ProductSnapshot映射到它们。 ProductSnapshot本身很可能可以用作EF实体,因此您不需要执行任何映射。

问题是,拍摄快照似乎是域行为。您只有在获得快照后才处理EF,并且完全按照与其他业务对象相同的方式执行操作。

+0

您如何看待绑定问题,因为如果我只有一个ProductSnapshot类型的属性,那么该属性将为null,直到OrderLine被确认,并且同样的事情会发生,如果我有一个产品类型的属性,但在相反的情况? –

+0

我想你误解了我。产品快照是一个将由存储库保存的业务对象。 OrderLine类可能包含产品快照,但这不是EF问题。存储库应该知道如何在有或没有产品或快照的情况下组装ORDERLine。该存储库使用EF来获取相关数据,然后将所有内容放在一起。简而言之,保持Domain和Persistence层分离,并且在建模业务对象时不要混合ORM。 ORM可帮助您更轻松地使用db,但存储库负责处理业务对象。 – MikeSW

+0

您必须决定此处的OrderLine,Product和ProductSnapshot是否是业务对象,或者它们是我希望不用于对域进行建模的EF实体。 – MikeSW

0

为什么OrderLine必须具有ProductSnapshot属性?我想,如果您需要获取历史信息,您可以从产品类链接到产品快照,或者,如果您只是想在某些条件下保存产品状态,只需在产品部分类中实施SaveSnapshot方法,或者它的扩展方法。