2011-12-06 51 views
10

我有一個簡單的兩個聚合根和一個正則實體的檢查域。 TenantUserGroupUser這種特定樣品中TenantUser彌補兩個AggregateRoots域事件處理程序什麼時候開始使用?

當從UI /服務層接收到命令時,它會到達操作只寫域的命令處理程序。

可以說,User不應該是一個AggregateRoot可言,但因爲它會被別人引用,它不可能是一個普通的實體。 (是的?)

這兩個AggregateRoot需要進行通信。 A User不能在不屬於UserGroup的情況下創建,該UserGroupTenant的有界上下文中的實體。據推測,我們可以通過構造函數創建一個User,因爲它是一個簡單的約束。 User.Create(TenantId, UserGroupId)

它生成一個帶有Date,AggregateVersion和AggregateId(用戶)的DomainEvent。現在我們到了模糊的部分。

打開提交此事件到商店,此事件廣播到公共汽車(內存,無論)。這就是域的事件處理程序(類似於命令處理程序)捕獲創建的用戶並通知/操縱TenantUserGroup以添加UserId

我的想法是解決這個問題的方向是完全錯誤的嗎?

+1

您可以通過重新考慮您的模型來簡化您的問題。當您需要跨界有限的上下文通信時,或者您希望支持業務邏輯(例如電子郵件通信)來響應域事件時,域事件會很有幫助。你的模型是否需要多個有界的上下文?您是否可以在服務層中包含所有必需的操作,例如UserService? – eulerfx

+0

你應該經常檢查你是否不能模擬這個問題。然而,在這種情況下,它是一個人爲的例子,旨在獲得關於不同有界AR之間的通信應如何發生的答案。 – Jaapjan

+0

「UserGroup中的未來行爲需要UserId?」是一個非常重要的問題(否則你爲什麼要在聚合之間進行交流)。如果您的域名不是多租戶(不要與多租戶混淆爲非功能性需求),讓租戶成爲您域名的一部分似乎很奇怪。如果他們在同一個BC中,請使用您的域對象與一些TDA進行協作。 –

回答

6

A Saga可能是你在找什麼。

簡而言之:一個傳奇可以實現爲一個事件處理程序,用於偵聽特定事件並向不同的聚合根發佈命令,甚至跨越上下文邊界。

在你的情況可能是這樣的:

public class RegisterUserSaga : Handles<UserCreated> 
{ 
    public void Handle<UserCreated>(UserCreated evnt) { 
     var tenantId = // you probably know how to find this 
     var groupId = // same here 
     var command = new RegisterUserForTenant(evnt.UserId, tenantId, groupId); 
     Bus.Send(command); 
    } 
} 

瞭解更多關於this article傳奇由里納特阿卜杜林或烏迪大漢看"CQRS, race conditions, and sagas - oh my!"

更新:

我們擴展後在評論中的討論我將嘗試展示這可以從另一個角度如何工作(前面的僞代碼)。希望這可以解決一些可能的解決方案:

// Aggregates: 

Tenant 
    Guid TenantId 
    List<Guid> UserGroups 

UserGroup 
    Guid UserGroupId 
    List<Guid> Users 

User 
    Guid UserId 
    Some more details 

// Commands: 

RequestRegistration(userId, userGroupId, user details) 
CreateUser(userId, user details) 
AddUserToGroup(userId, userGroupId) 

// The initial command would be: 

RequestRegistration (leading to a RegistrationRequested event) 

// The Saga handles the RegistrationRequested and all subsequent events 

UserRegistrationSaga 
    Handle(RegistrationRequested) 
    -> send CreateUser command (which eventually leads to a UserCreated event) 
    Handle(UserCreated) 
    -> send AddUserToGroup command (-> UserAddedToGroup event) 
    Handle(UserAddedToGroup) 
    -> Done 
+0

如果可能的話,如果我有正確的順序,你可以點亮嗎?改變AR,承諾ES,廣播事件,Saga選擇並更改其他AR等等?這需要一些機制來喚醒,instanciate並定期致電佐賀的,是的? – Jaapjan

+0

這正是我想到的順序。像任何其他事件處理程序一樣,基本的無狀態saga實現可以簡單地在啓動時註冊。更復雜的實現可能包括持久性。對於初學者來說,簡單的無狀態實現應該足以適應這個概念。對於更復雜的變體,請查看NServiceBus和Jonathan Oliver在GitHub上的Common Domain/Event Store的傳奇故事。 –

+0

在這種特殊情況下,由於用戶創建的事件可能不會立即被傳奇人士拿走,我們正在處理域中的最終裁決,是的?由於用戶可能已被「添加」到租戶的組,但租戶AR尚未更新? – Jaapjan

相關問題