6

我一直在研究域驅動設計與domain events。我真的很喜歡這些事件提供的分離關注點。我遇到了一個持久化域對象和引發域事件的問題。我想在域對象中引發事件,但我希望它們是持久性的無知。持久性和域名事件與持久性的無知對象

我已經創建了一個基本的ShoppingCartService,用這種方法Checkout

public void Checkout(IEnumerable<ShoppingCartItem> cart, Customer customer) 
{ 
    var order = new Order(cart, customer); 

    _orderRepositorty.Add(order); 
    _unitOfWork.Commit(); 
} 

在這個例子中,Order構造函數將引發OrderCreated事件可以通過一定的處理程序進行處理。但是,我不希望在實體未持續存在或持續存在失敗時提出這些事件。

爲了解決這個問題,我已經找到了幾種解決方案:在服務

1.引發事件:

而不是在域對象引發事件,我可以提高在服務事件。在這種情況下,Checkout方法會引發OrderCreated事件。這種方法的缺點之一是,通過查看域對象,不清楚哪些事件是由什麼方法引發的。另外,開發人員必須記得在其他地方創建訂單時提出該事件。它感覺不對。


2.隊列域事件

另一種選擇是要排隊域事件,並提高他們堅持成功的時候。這可能是由using聲明例如可以實現:

using (DomainEvents.QueueEvents<OrderCreated>()) 
{ 
    var order = new Order(cart, customer); 

    _orderRepositorty.Add(order); 
    _unitOfWork.Commit(); 
} 

QueueEvents<T>方法將一個boolean值設置爲trueDomainEvents.Raise<T>方法將排隊的事件,而不是直接執行它。在QueueEvent<T>的處置回調中,排隊的事件被執行,以確保持續已經發生。這似乎相當棘手,它需要服務知道在域對象中引發哪個事件。在我提供的例子中,它也只支持一種類型的事件被提出,但是,這可以被解決。


3.堅持域事件

我可以使用域事件持續的對象。這似乎沒問題,除了事件處理程序持久化對象應該先執行,但是我在某處讀取域事件不應該依賴於特定的執行順序。也許這並不重要,域名事件可能會以某種方式知道處理程序應該以何種順序執行。例如:假設我有定義域事件處理接口,一個實現應該是這樣的:

public class NotifyCustomer : IDomainEventHandler<OrderCreated> 
{ 
    public void Handle(OrderCreated args) 
    { 
     // ... 
    } 
} 

當我想以處理使用事件處理程序過於堅持,我會創造另一個處理程序,推導從相同的接口:

public class PersistOrder : IDomainEventHandler<OrderCreated> 
    { 
     public void Handle(OrderCreated args) 
     { 
      // ... 
     } 
    } 
} 

現在NotifyCustomer行爲取決於被保存在數據庫中的順序,所以PersistOrder事件處理程序應首先執行。這些處理程序是否可以引入一個屬性來表示它們的執行順序?從DomainEvents.Raise<OrderCreated>()方法的實現一卡:

foreach (var handler in Container.ResolveAll<IDomainEventHandler<OrderCreated>>().OrderBy(h => h.Order)) 
{ 
    handler.Handle(args); 
} 


現在的問題是,我有什麼其他選擇?我錯過了什麼嗎?你對我提出的解決方案有什麼看法?

+0

您是否考慮過使用某種工廠或工廠方法創建新訂單?這將標示實例化訂單對象和「創建新訂單」之間的顯式差異。 – tuespetre

回答

6

您的(事務性)事件處理程序在(可能分佈的)事務中登記,或者在事務提交後發佈/處理事件。你的「QueueEvents」解決方案的基本思路是正確的,但有更多優雅的解決方案,比如通過存儲庫或事件存儲進行發佈。舉一個例子來看看

你也可以找到有用的這些問題和答案:

CQRS: Storing events and publishing them - how do I do this in a safe way?

Event Aggregator Error Handling With Rollback


更新於3點:

......但是我在某處看到域名事件d不依賴於特定的執行順序。

無論你如何堅持,事件的順序絕對重要(在一個聚合中)。

現在NotifyCustomer的行爲取決於保存在數據庫中的訂單,所以PersistOrder事件處理程序應該先執行。這些處理程序是否可以引入一個屬性來表示它們的執行順序?

堅持處理事件是獨立的顧慮 - 不要堅持使用事件處理程序。先堅持,然後處理。

+0

非常感謝您的回答。我已經更新了第3點,因爲我認爲你混合了升級_events_和執行_event處理程序的順序。你可以看看嗎?提前致謝。 –

+0

我已更新我的答案,希望它有幫助。 –

+0

感謝您的幫助,我想我現在已經明白了。 –