2011-01-14 50 views
18

在我們的應用程序中,當域模型中的某些內容發生變化時,我們提出域事件。由事件處理程序執行的一些任務必須在引發事件時使用的同一事務內完成,其他任務必須在此事務之外執行。域名事件是否應該在交易內部或外部引發?

例如,

當訂單項目被添加到順序的實體,所述OrderLineAdded域事件引發,一個域事件改變域模型(因此必須在同一事務中執行)的狀態,然後當交易完成後,UI必須更新。

你會如何解決這個問題?

  1. 引發兩個事件,一個在事務中,另一個在事務之外。
  2. 在事務內部引發事件,但使用事件處理程序發送異步請求以更新UI?

方案1還是很迷惑,因爲事件名稱必須以某種方式傳達他們或退出交易的,但與選項域事件的處理2必須始終認爲他們是從一個事務中同步調用。

也許有更好的方法?

回答

16

我有過類似的問題。領域模型發佈事件(使用Udi Dahan描述的技術here)。然後我意識到,即使出現錯誤並且事務稍後回滾,我的UI相關處理程序也會被調用。

爲了解決這個問題,我在系統中引入了另一種角色,即另一種事件處理程序。我有ITransactionalEventHadnelerINonTransactionalEventHandler。前者在DomainEvents.Publish()方法中立即被調用。只要事務被提交,後者就被排隊調用(使用System.Transactions掛鉤)。該解決方案工作正常,是非常可讀和可維護的。

+0

這聽起來像是一個很好的解決方案,您如何命名事件以區分事務性事件和非事務性事件? – Andronicus 2011-01-19 15:22:26

1

我覺得這兩個辦法可以是很好的,只是堅持同樣的方法在你的代碼的每一部分:

  1. 你將需要兩個(或更多)的事件處理程序,一個用於域的上下文模型在事務範圍內,以及輔助上下文的其他模型(如UI)。您的域代碼不應該關心代碼的其他部分,只要通知他們有關域數據的更改。
  2. 您的域代碼事件處理程序方法可能會向UI或其他模塊發送異步事件。域事件應該是同步的,否則你需要兩階段提交才能保持事務性。

我個人更喜歡選項2,因爲它保持域代碼更清潔,並且通過使用異步通信,核心和其他模塊將被解耦,因此外部模塊中的問題不會妨礙核心的工作。另一方面,可能會出現選擇1更有利的情況。

相關問題