首先也是最重要的:CQRS和关系数据库不会相互排斥。在高级场景中,将基于 SQL 的 DB 替换为其他存储方式可能是有意义的,但 CQRS 作为一个概念并不关心持久性机制。
在依赖于角色和/或用户的多个视图的情况下,精简读取层可能应该提供多个结果集:
- 一个包含被授权访问该信息的用户的完整 SSN。
- 为无权查看该信息的用户提供不同的信息
- ...
这些可以存储在单独的数据存储中,但如果您使用单个基于 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 中名为CustomerListForSally、CustomerDetailsForSally等的几个文档。这些文档填充了她允许查看的内容。
一旦她得到提升——这将是一个重要的领域事件——她所有的非规范化数据将被自动覆盖,并扩展为包含她现在可以看到的内容。
当然,我们必须保持理性和务实,但这个理想应该是我们前进的大方向。
实际上,您可能拥有某种基于用户/角色或用户/组的系统。为了能够查看敏感信息,您必须是特定角色或组的成员。这些中的每一个都可以有它们定义的视图和命令集。这不需要去噪数据它可以像 SQL-Views 一样简单:
- CustomerDetailsForSupportStaff
- 具有未屏蔽 SSN 的CustomerDetailsForSupportExecutive
- 支持人员的客户名单
- CustomerListForSupportExecutive与客户总收入
- 等等