Jaa*_*jan 10 c# events domain-driven-design cqrs domain-events
我有一个简单的两个聚合根和一个常规实体的检查域.
Tenant
,UserGroup
以及User
在这个特定样本中的位置Tenant
和User
弥补两个AggregateRoots.
当从UI /服务层接收到命令时,它到达操作只写域的命令处理程序.
您可以说User
根本不应该是AggregateRoot,但由于它将被其他人引用,因此它不能是常规实体.(是?)
这两个AggregateRoot需要进行通信.A User
不能在不属于a的情况下创建,a UserGroup
是有界上下文中的实体Tenant
.据推测,我们可以通过构造函数创建一个用户,因为它是一个简单的约束.User.Create(TenantId, UserGroupId)
它生成一个DomainEvent
with Date,AggregateVersion和AggregateId(用户).现在我们来到模糊的部分.
打开将此事件提交到商店,此事件将被广播到总线(内存,无论如何).这一点,该点域的事件处理程序,类似命令处理,抓创建的用户,并通知/操纵Tenant
的UserGroup
添加UserId
?
我对解决这个问题的想法是否会走向完全错误的方向?
一个Saga
可能是你在找什么.
简单地说:一个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);
}
}
Run Code Online (Sandbox Code Playgroud)
在Rinat Abdullin的这篇文章中阅读更多关于传奇的内容,或者观看"CQRS,竞争条件和传奇 - 哦,我的!" 作者:Udi Dahan
更新:
在我们在评论中进行了扩展讨论之后,我将尝试从不同的角度展示这是如何工作的(伪代码).这有望为可能的解决方案提供更多信息:
// 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
Run Code Online (Sandbox Code Playgroud)