2013-10-27 56 views
2

在正常的DDD項目中,我期望從存儲庫中檢索到的實體作爲DTO從域層發送到應用層。CQRS中的實體與DTO

似乎CQRS存在的一個原因是應用程序層(主要是讀取操作)所需的查詢與領域層所需的查詢不同。所以看起來,即使是同一個對象的查詢結果可能在不同層次間也是不同的。

在我的域圖層中,我已經將查詢結果映射到域實體。我對一些將查詢結果直接映射到DTO的CQRS示例感到困惑,因爲它們跳過了匹配的實體。

假設數據庫返回:

{"person": { 
    "id:": 5323423, 
    "name": "John", 
    "family_name": "Smith" 
    ... 
}} 

然而,實體佈局映射

class Person 
{ 
    Identity id; 
    String name; 
    String surname; 
} 

如果發生這種情況在一些CQRS例子我所看到的,提取的DTO看上去會有所不同,在將實體與其DTO進行匹配時會導致衝突。這些衝突如何解決?在我看來,任何DTO(與實體有關)都應該始終從其實體生成。但是,在這種情況下,應用程序層中執行不同類型查詢的自由會丟失。

回答

3

關鍵是你不要將實體映射到DTO。 DTO由特定上下文所需的內容定義,併成爲查詢/讀取模型。當實體更新時,事件處理程序將使用它來更新讀取模型。

所以基本上讀取的模型是從所有需要的實體(1個或更多)生成和更新的,通常是以增量的方式。

+0

在我的示例中,如果來自讀取模型的DTO由用戶(系列名稱)修改,那麼GUI將引發具有將到達域層的DTO的命令。在域層內我可以讀取或生成DTO,但只能將實體保存回數據庫。因此,我假設在保存修改時,必須將DTO映射到其實體。如果您只是從數據庫中將新值更新到實體中,那麼修改如何在不通過實體和不匹配字段名稱的情況下保存到數據庫中? – SystematicFrank

+0

閱讀模型生成不是域層的一部分,而是服務或應用程序,但顯然不是域,因爲它是關於模型在其外部使用的。修改被保存到Db中,但任何更改都會生成域事件。事件處理程序將更新讀取模型,然後將其發送到查詢存儲庫進行保存。如果您希望所有內容都在存儲庫層完成同步,那麼您可以在那裏更改讀取模型(仍然調用服務)並在更新後才返回。 – MikeSW

+0

可悲的是我的強硬路線仍然是經典的DDD。使用普通的DDD,我使用實體對象在我的域圖層中映射任何從/到DB的任何回購。你的意思是查詢庫(寫/命令模型?)(CQRS之前的DDD中的簡單回購)不僅可以將一個實體作爲輸入,而且可以將來自這種實體的不同「成形」DTO?這樣,仍然是一個數據映射器只適用於一個實體,但它的數據庫中的DTO可以堅持未來的實體值,而無需數據映射,只要提供一個ID? (非常接近我的阿哈!瞬間) – SystematicFrank

4

完全贊同@MikeSW,只需添加一張圖(借用軸突框架)來解釋架構。

enter image description here

的readmodel通過查詢用例驅動,你可以認爲這是命令操作的輸出。