问题标签 [domain-events]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
cqrs - CQRS 和领域事件
CQRS 让我进入了思考模式。我正在尝试用 CQRS 的想法开始一个新项目。我喜欢的主要事情是
1) 查询和命令的分离。我们的域查询一直是个问题。
2) 使用事件存储进行审计——我不会将它用于重放——至少现在不会。
我擅长查询方面,但我仍然对领域事件有一些疑问
如果命令导致更新多个聚合根(例如 Order 和 OrderDetail),我会将它们的范围限定在 UnitofWork(事务性)下。现在每个域都负责在其状态发生更改时发布事件。
假设该命令更改了 3 个 orderDetail 记录。每个 OrderDetail 将发布 2 个事件。最后我们有 6 个事件。
a)如果我在对域对象进行更改后立即发布事件(但未提交事务),我如何撤消已发布的事件(并且可能已被订阅者消费)
- 我能想到的是将要发布的事件保存在“在同一工作单元范围下”的列表中,一旦调用了事务提交,就将其存储并发布。这听起来是不是一个人会做的事情。
b) 如果 OrderDetail 中的更改要求 Order Aggregate Root 中也发生一些更改,那么
i) 我是否应该通过处理 OrderDetail Aggregate 发布的事件来基于这些更改?例如。让我们说两个订单详细信息被删除。这使得订单状态从 "preferred" 变为 "Not preferred" 。ii) 如果事件发生错误并且不更新订单状态怎么办 - 如果订单仍然是首选,那么它会在 2 天内发货。
添加另一个问题
c)“域事件是所有应用程序状态更改的来源”还是“所有应用程序状态更改的结果”
先感谢您,
三月
domain-driven-design - 将 CQRS 和 DDD 与域事件和 ServiceBus 一起使用时在视图中显示更改
我对使用域事件构建读取模型的系统中的流程有点困惑。特别是,我们如何处理用户期望数据(及其视图)在他们完成命令时发生变化的事实,但由于我们的系统架构(发布事件的非阻塞调用),实际数据库可能不会在页面是否重新加载?
我希望使用事件和服务总线将我们其中一个系统的设计与 CQRS 更加内联。
假设我的流程是这样的:
用户单击视图中的按钮以执行从其帐户中删除付款方式的任务。
控制器调用 PaymentMethodRemovalService,将 accountId 和 paymentMethodId 传递给它。
控制器使用 AccountRepository 检索 Account 并调用 account.RemovePaymentMethod(id)
帐户验证可以发生操作并发布事件 PaymentMethodRemovedMessage(accountId, paymentMethodId)
因为事件发布是异步的,我们现在必须从服务返回并从控制器返回视图——但我们的实际数据还没有更新!
处理程序 IHandle< PaymentMethodRemovedMessage > 听到事件并从数据库中删除实际行
那么,男人该怎么办?
我可以简单地说,删除显示付款方式的 div。这可能适用于 AJAX 场景,但如果我使用 Post-Redirect-Get 来支持非 JavaScript 客户端怎么办。然后我将触发我的 Get 并从 Query 端读取数据,可能在更新之前。
我是否只显示一条通知,说明他们删除付款方式的请求已提交?(这似乎并不友好,对于提交订单有意义,但对于更改地址则不然)。
有没有办法协调将更改实现为分离的异步事件并显示反映其当前更改的用户数据?
编辑:我的问题与CQRS、DDD 同步报告数据库非常相似, 我不得不说,那里给出的答案以及这里也提到的,有点味道 - 争吵 UI 以显示带外的更新可以这么说,读取数据库。我希望有一些更清洁的东西。
.net - 领域事件、EventHandlers、Dispatcher 的哪一层
我一直在阅读有关领域事件的内容,并看到了 Udi 实现的代码(http://www.udidahan.com/2009/06/14/domain-events-salvation/),Mike Hadlow(http://mikehadlow.blogspot。 com/2010/09/separation-of-concerns-with-domain.html),Jimmy Bogard 和 Jason Dentler 的实现。
总而言之,我喜欢事件的概念。
我的问题是我应该在哪一层添加这些组件。
我不会使用任何 BUS,所有事件都将以同步方式处理。
我猜接口 IDomainEvent , IEventHandler 应该进入Project.Core其余接口由所有项目保存和访问。
我认为 Dispatcher (这是一个静态类)应该进入Project.Infrastructure。
我将为领域事件的处理程序创建一个新项目。让我们说Project.EventHandlers。
我将使用 IoC(结构映射)来注册所有处理程序。
我看到的事件本身是基于商业语言的,因此我认为应该去Project.Domain实现所有聚合。
让我知道这是否是正确的方法。
我的另一个困惑是项目参考。应该Project.Domain引用Project.Infrastructure以便它可以使用静态Event Dispatcher。
Project.EventHandlers是否应该引用Project.Domain ,因为它需要知道可以处理哪些事件。
我计划在Project.EventHandlers中创建一个 StructureMap Registry 类,然后在 Global.asax 中引导。
如果之前已经讨论过,请指向我的链接。我无法通过 Google 搜索找到一个。
c# - 寻找领域事件的例子
有谁知道在哪里可以找到Udi Dahan在Domain Events – Salvation中描述的领域事件实现的示例代码?
architecture - 领域事件处理程序——它们应该用于应用层问题吗?
在实现领域事件时,事件处理程序应该只用于纯粹的领域问题;您会与业务专家讨论的东西,或者它们是否可以被任何对领域模型感兴趣的人使用?
这很可能用一个简单的例子来解释,考虑一个日历应用程序来安排员工的工作。
我们可能有以下领域事件...
AppointmentAdded AppointmentRemoved AppointmentContentChanged AppointmentMoved
我们有这些事件的处理程序,例如,当约会移动到员工工作时间之外的时间时,我们设置了一个警告标志。
当然,有一些应用程序对这些事件感兴趣,例如,当一个约会被添加到日历中时,我们应该将它添加到工作单元中,以便我们以后可以提交更改。
这些应用程序关注点应该是领域事件的消费者,还是我们应该提出并处理单独的系统事件?
architecture - 应该在事务内部还是外部引发领域事件?
在我们的应用程序中,当域模型发生变化时,我们会引发域事件。事件处理程序执行的某些任务必须在引发事件时使用的同一事务中完成,其他任务必须在此事务之外执行。
例如,
当 Orderline 添加到 Order 实体时,会引发 OrderLineAdded 域事件,一个域事件会更改域模型的状态(因此必须在同一事务中执行),然后当事务完成时,必须更新 UI。
你会如何处理这个问题?
- 引发两个事件,一个在事务内部,一个在事务外部。
- 在事务内部引发事件,但使用事件处理程序发送异步请求以更新 UI?
选项 1 似乎令人困惑,因为事件名称必须以某种方式传达它们是在事务中还是在事务之外,但是对于选项 2,域事件的处理程序必须始终假定它们是从事务中同步调用的。
也许有更好的方法?
event-handling - 领域事件 v 事件聚合器 v... 其他
我的域中有一个复合结构,其中叶节点(分配)有一个 DurationChanged 事件,我想在表示层视图模型结构的顶部(在 TimeSheetViewModel 中)使用该事件,我想知道最好的方法是什么去实现它。
想到的选项包括:
- 在 TimeSheetComposite 中订阅它。每个组合最终都由 Allocations 组成,TimeSheetComposite 是 TimeSheetViewModel 的 Model。似乎我还需要 TimeSheetComposite 中的一个事件,该事件在子 DurationChanged 事件被触发时被触发;TimeSheetViewModel 将订阅后一个事件。
- 忽略 DurationChanged 事件,并在 AllocationViewModel.Amount 更改时跟随冒泡到 TimeSheetViewModel 的 INPC 链。我不会有有用的信息,特别是编辑前的旧 Amount,但如果有必要,我可以足够便宜地计算所需的最终结果。
- 使 DurationChanged 事件成为领域事件;我目前不使用域事件,但我确实喜欢这个概念,而且看起来 Udi 的文章中有足够的代码可以开始使用它。
- 设置某种事件聚合器来发布和订阅 DurationChanged。我还不太确定领域事件和事件聚合器之间的区别是什么,以及它们是解决同一问题的补充方法还是替代方法。这里使用 Rx的实现看起来很有希望。
在此设计中,TimeSheetViewModel 需要知道 Allocation.Duration 何时发生更改,以便它可以按日期获得所有分配持续时间的新总数。
您将如何提供 DurationChanged 通知?
干杯,
贝里尔
领域复合结构和事件
表示层结构
autofac - 将 Autofac 与域事件一起使用
我正在尝试将领域事件引入项目中。这个概念在 Udi Dahan 的帖子中有所描述 - http://www.udidahan.com/2009/06/14/domain-events-salvation/
这是域事件代码
最重要的部分是 IEventDispatcher 实现,它将域事件与引发事件时需要发生的任何事情分离。诀窍是通过一个容器连接这个耦合。这是我的尝试
注册所有域事件处理程序的代码......
并解析调度程序中的所有事件处理程序。问题是没有处理程序被解决。
所以我没有正确注册事件处理程序或没有解决它们。如何检查注册是否有效?
处理程序的示例代码
更新 经过反复试验,EventDispatcher 工作正常!如果我手动注册一个处理程序,然后触发它工作的域事件。程序集扫描/注册是我的问题。手动注册码...
那么我如何扫描所有程序集,IHandleDomainEvents<>
因为它们看起来像这样
asp.net-mvc - 在 asp.net mvc 控制器中处理域事件
我正在研究使用域事件从发生在我的域模型深处的操作中提取信息,以便在控制器级别发出某些事件的信号。不幸的是,我无法找到如何在 asp.net mvc 控制器上正确连接它的示例。
简而言之,这就是我在行动中寻找的内容:
谁能给我一些指导?
更新
为了清楚起见,我了解如何在控制器中引发和处理域事件;我只是在寻找一种在我所描述的上下文中可以安全使用的事件注册实现。
asp.net-mvc - 在哪里引发依赖于持久性的域事件 - 服务、存储库或 UI?
我的 ASP.NET MVC3 / NHibernate 应用程序需要触发和处理与我的域对象相关的各种事件。例如,一个Order
对象可能有类似OrderStatusChanged
或的事件NoteCreatedForOrder
。在大多数情况下,这些事件会导致发送电子邮件,因此我不能只将它们留在 MVC 应用程序中。
我已经阅读了 Udi Dahan 的Domain Events和许多其他关于如何做这类事情的想法,我决定使用基于 NServiceBus 的主机来处理事件消息。我已经做了一些概念验证测试,这似乎运作良好。
我的问题是哪个应用程序层实际上应该引发事件。在成功持久化相关对象之前,我不想触发事件(如果持久化失败,则无法发送创建便笺的电子邮件)。
另一个问题是,在某些情况下,事件与聚合根下的对象相关联。在上面的示例中,Note
通过将 a 添加到Order.Notes
集合并保存订单来保存它。这带来了一个问题,因为很难评估Order
保存 an 时应该触发哪些事件。我想避免在保存更新的副本之前提取对象的当前副本并查找差异。
UI 是否适合引发这些事件?它知道发生了哪些事件,并且只有在服务层成功保存对象后才能触发它们。让控制器触发域事件似乎有些不对劲。
成功持久化后存储库是否应该触发事件?
我应该完全分离事件,让存储库存储一个
Event
对象,然后由轮询服务获取,然后变成 NServiceBus 的事件(或直接从轮询服务处理)?有一个更好的方法吗?也许只有在对象被持久化后才让我的域对象排队由服务层触发的事件?
更新:我有一个服务层,但是让它通过比较过程来确定在保存给定的聚合根时应该触发哪些事件似乎很麻烦和过度。因为其中一些事件是细粒度的(例如“订单状态已更改”),我想我必须检索对象的数据库副本,比较属性以创建事件,保存新对象,然后将事件发送到 NServiceBus保存操作成功完成。
更新
在我在下面发布的答案之后(在下面),我最终做的是在我的域实体中构建EventQueue
一个List<IDomainEvent>
. 然后,我添加了对域进行更改的事件,这使我能够将逻辑保留在域内,我认为这是合适的,因为我是根据实体内发生的事情触发事件。
然后,当我将对象持久保存在我的服务层中时,我会处理该队列并将事件实际发送到服务总线。最初,我计划使用使用身份 PK 的遗留数据库,因此我必须对这些事件进行后处理以填充实体的 ID,但我最终决定切换到Guid.Comb
允许我跳过该步骤的 PK。