2011-04-21 49 views
6

我一直試圖在udi dahan描述的一個新項目中實現這個模式。使用域事件模式

我喜歡if的想法,但我不太確定它應該在什麼情況下應用(對這個東西來說是新的......)。

例如讓我說我有一個事件OnUserCreated。我希望其中一個處理程序向用戶發送確認電子郵件。但是如果事件被觸發了,電子郵件就會被髮送,然後在提交事務時出錯,並且數據永遠不會保存到數據庫中。該模式適用於這種情況嗎?我讀過人們說不,但我已經做過的一些項目實際上是這樣做的。或者這是我應該只用於加載和更新其他實體的東西......另一方面,我讀某人說,操作所需的相關實體應該已經加載,所以我不應該從數據庫中加載它們事件。

回答

7

這當然取決於你如何選擇實現你的系統。

你可以在這裏考慮多種選擇:

1.兩階段提交 當執行兩階段提交,基本上每個處理器包含3種方法:一個準備,一個承諾和一個卷背部。

對於所有的事件處理程序,Prepare首先被調用。如果這些報告都沒有問題,則調用所有處理程序的Commit()方法。如果其中任何一個報告有問題 - 儘管Prepare()調用沒有報告問題 - 那麼對於已經執行了Commit()的所有處理程序,您可以調用它們的Rollback()方法。

2.內部和外部事件處理程序 另一種選擇是使事件處理程序的一個分離。你可以發佈一個事件,比如UserCreated,它由事件處理程序首先參與事務處理。事件作爲事務的一部分存儲在數據庫中。然後,您可以擁有僅對已存儲在數據庫中的事件做出反應的外部事件處理程序 - 例如您的電子郵件發件人。這些只能在初始事務提交後才能調用。

我相信你可以想出更多的方法來處理你的具體情況。

3

使用域事件允許您在業務事務(創建用戶)之外移動某些操作(發送電子郵件)。事件的發佈與db事務處理相同,所以如果db事務失敗,事件將不會被髮布。使用持久的消息隊列系統(msmq)可確保如果事件已發佈,處理程序將最終執行。

你流應該是這個樣子:

Begin Transaction 
    Receive Command 
    Call Aggregate Method 
     Publish Events // will only be published if the transaction succedes 
Commit Transaction 

Begin Transaction 
    Receive Event 
    Send Email 
End Transaction 

作爲一個側面說明嘗試命名事件,而在「開」的前綴,因爲它更容易在句子中使用它們。