【问题标题】:Domain queries in CQRSCQRS 中的域查询
【发布时间】:2011-01-02 04:40:08
【问题描述】:

我们正在试用CQRS。我们有一个验证情况,客户服务(域服务)需要知道客户是否存在。客户的电子邮件地址是独一无二的。我们的客户存储库(通用存储库)只有 Get(id) 和 Add(customer)。 CustomerService 应该如何确定 Customer 是否存在?

【问题讨论】:

    标签: domain-driven-design cqrs


    【解决方案1】:

    看看这篇博文:Set based validation in the CQRS Architecture

    它解决了这个问题。这是在 CQRS 中处理的复杂问题。 Bjarte 的建议是查询报告数据库中现有的客户电子邮件地址,并在找到电子邮件地址时向域模型发出补偿命令(例如CustomerEmailAddressIsNotUniqueCompensatingCommand)。然后,您可以触发适当的事件,其中可能包括 UndoCustomerCreationEvent

    通读上述博客文章中的 cmets 以获得替代想法。

    Adam D. 在评论中建议验证是一个域问题。因此,您可以将 ReservedEmailAddresses 存储在有助于创建客户并由事件存储中的事件补充的服务中。

    我不确定这个问题是否有一个简单的解决方案,感觉完全干净。让我知道你的想法!

    祝你好运!

    【讨论】:

    • 如另一个答案中所述,您不应在处理命令的过程中对视图模型执行查询。如果有的话,这些查询应该由客户端在发送命令之前执行,根据结果选择不发送命令。
    • @Udi Dahan 从 SOA 的角度来看,这个用户名示例我并没有真正理解它是如何工作的。当我收到 CreateNewUserCommand 时,我肯定需要检查用户名是否不存在?我不能假设客户已经完成了这项检查,特别是如果客户可能是第三方应用程序?我理解在处理命令时不执行查询的理由,但我可以想到一些场景,在处理命令时,我需要分析该命令旨在操作的聚合之外的数据...
    • 第三方应用程序将通过一个行为良好的“客户端”进行连接,该客户端可能是一个 Web 服务,它是对视图模型进行检查的客户端,如果检查通过,则发送向“服务器”发送单向消息。
    • 作为 David 评论基础的 SOA 的全部要点是支持集成和扩展等。因此,最基本的规则之一就是永远不要信任。因此,我们应该始终在提交之前进行验证/验证。
    • @inf3rno 或当您的投影或事件总线卡住时。想象一下周末的这种情况,一个用户重复执行CreateNewUserCommand,最终为同一用户聚合了 100 多个用户。这确实是一个巨大的故障点,似乎没有人知道如何正确解决。 (我也不知道,否则 Google 不会把我带到这里 :p)
    【解决方案2】:

    这个问题不必那么复杂:

    1. 在提交 UpdateCustomer 命令之前检查您的报告存储中的客户唯一性。
    2. 为您的数据库添加一个约束,以确保电子邮件地址的唯一性。执行命令时,处理异常并使用回复通道向用户发送通知。 (因此永远不会向报告存储触发 CustomerUpdated 事件。

    将数据库用于它的优点,不要被 ORM 限制所困扰。

    【讨论】:

    • 如果不是数据库怎么办
    • 并发命令怎么样?在某些(罕见但可能的)情况下可能会创建两个客户。
    【解决方案3】:

    Udi Dahan http://www.udidahan.com/2009/12/09/clarified-cqrs/ 的这篇帖子包含以下段落:

    “此外,我们不应该需要访问查询存储来处理命令——任何需要的状态都应该由自治组件管理——这是自治含义的一部分。”

    我相信 Udi 建议简单地向数据库添加一个唯一约束。

    但是,如果您不想这样做,根据上面的陈述,我建议您将“ByEmail”方法添加到存储库并完成它 - 但是 Udi 可能会有更好的建议。 .

    【讨论】:

    • 这并不适用于所有场景,例如,我使用的 NoSQL 数据库不支持“约束”的概念。
    • @james 什么nosql数据库?
    【解决方案4】:

    希望我还不算太晚...但是我们在项目中遇到了类似的情况,我们实际上拦截了命令执行程序并将其附加到为该命令创建的规则集,然后使用查询来获取数据。

    所以在这种情况下,我们可以有一个名为 CustomerEmailMustBeUniqueRule 的类,当 RegisterCustomerCommandExecutor 将要执行命令“RegisterCustomerCommand”时,它由 RuleEngine 获取。该规则类负责查询数据库以查找电子邮件 ID 是否存在并通过引发无效标志来停止执行...

    【讨论】:

      猜你喜欢
      • 2015-11-19
      • 2016-11-27
      • 2014-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-04
      相关资源
      最近更新 更多