5

所以我喜欢在我们的应用程序中使用 CQRS 的概念,主要是因为我们已经支持事件溯源(从概念上讲,不遵循你看到的任何规定)。然而,CQRS 似乎真的是面向大数据、最终一致性之类的东西。我们总是会成为一个关系数据库应用程序,所以我不确定它是否合适。

我也有顾虑,因为我认为我需要在我的应用层做一些特殊的事情。在进行读取时,我需要强制执行安全性和过滤数据,这些都是传统上在应用层中实现的东西。

我的第一个问题是,我的应用程序是否适合(传统的 MVC / 关系数据库应用程序)?还是拥有传统的应用程序层并使用 DTO 映射器更有意义?

我的第二个问题是,从传统应用层向域模型发出命令是否有意义?我喜欢命令/命令处理程序和事件的想法。

让我澄清一下我的问题。我担心与授权相关的数据过滤。当用户请求数据时,必须有一个过滤器来限制对某些数据元素的访问,方法是将它们全部删除(因此它们不会返回给调用者)、隐藏值或对数据应用掩码。在一个人为的示例中,对于社会安全号码,发出请求的用户可能只能看到最后 4 个数字,因此结果将显示为 ###-##-1234。

我的断言是,这个责任在应用层。我认为这是一个方面,对查询或命令的所有响应都必须通过这种过滤机制。这就是我的 CQRS 天真的地方,也许是命令从不返回数据,只是指向通过读取模型查找的数据的指针?

谢谢!

4

1 回答 1

10

首先也是最重要的:CQRS关系数据库不会相互排斥。在高级场景中,将基于 SQL 的 DB 替换为其他存储方式可能是有意义的,但 CQRS 作为一个概念并不关心持久性机制。

在依赖于角色和/或用户的多个视图的情况下,精简读取层可能应该提供多个结果集:

  1. 一个包含被授权访问该信息的用户的完整 SSN。
  2. 为无权查看该信息的用户提供不同的信息
  3. ...

这些可以存储在单独的数据存储中,但如果您使用单个基于 SQL 的数据库,它们也可以通过 SQL 视图提供。

在 CQRS 中,Application Service仍然以Command Handlers的形式存在。这些可以嵌套,即首先处理授权,然后将命令发布到包含的命令处理程序。

public class AuthorizationHandler {

    public CrmAuthorizationService(CrmCommandHandler handler) {
        _next = handler;
    }

    public void Handle(SomeCommand c) {
        if (authorized) _next.Handle(c);
    }
}

// Usage:
var handler = new CrmAuthorizationService(new CrmCommandHandler());
bus.Register<SomeCommand>(handler.Handle);

通过这种方式,您可以嵌套多个处理程序,例如作为REST 信封,用于日志记录事务等。

要回答您的问题:

第一: CQRS 是否适合您的应用程序?如果不真正深入研究具体要求,谁也说不出来。就 CQRS 的优缺点而言,仅仅因为您使用 MVC 和关系数据库并没有任何意义。

第二:是的,在某些情况下,让您的应用程序层以经典方式与客户端交互并处理身份验证、授权等事情,然后在内部发出命令是有意义的。这在将基于 MVC 的 UI 或 REST API 放在应用程序之上时会很有用。

更新以回应评论:

在一个理想的、纯粹的 CQRS 场景中,Sally 会为每个视图拥有自己的非规范化数据,例如 NoSQL DB 中名为CustomerListForSallyCustomerDetailsForSally等的几个文档。这些文档填充了她允许查看的内容。

一旦她得到提升——这将是一个重要的领域事件——她所有的非规范化数据将被自动覆盖,并扩展为包含她现在可以看到的内容。

当然,我们必须保持理性和务实,但这个理想应该是我们前进的大方向。

实际上,您可能拥有某种基于用户/角色或用户/组的系统。为了能够查看敏感信息,您必须是特定角色或组的成员。这些中的每一个都可以有它们定义的视图和命令集。这不需要去噪数据它可以像 SQL-Views 一样简单:

  • CustomerDetailsForSupportStaff
  • 具有未屏蔽 SSN 的CustomerDetailsForSupportExecutive
  • 支持人员的客户名单
  • CustomerListForSupportExecutive与客户总收入
  • 等等
于 2012-09-27T15:38:25.393 回答