从CQRS中的写入侧数据库中读取数据

时间:2017-01-05 09:11:14

标签: architecture cqrs

背景:

解释CQRS的图表通常会明确区分读写路径和单向数据流,如本示例所示(来源:Demystified CQRS):enter image description here

问题:

我想澄清一下,

如果后端的Command执行需要数据库中的某些数据,

  • “写入端”应该具有写数据库的一些读取功能吗?
  • 或者它应该完全依赖“读取方”进行任何读取?
  • 或者命令应该包含调用者提供的所有必需数据?

2 个答案:

答案 0 :(得分:4)

  

应该"写边"有一些来自写数据库的读取功能吗?

可能 - 加载将要运行命令的实体的最直接的方法是从"写入数据库"中读取它的状态。例如,在事件源体系结构中,通常通过从写入模型加载该实体的历史记录,从该历史记录中重新水化该实体,评估该命令以及将新的更改附加到历史记录来处理更新事件源实体的命令。

读取关于处理命令的实体的状态是另一回事 - 词汇在这里有帮助;您正在修改的状态只属于一个聚合,只要有可能,就应该将生成在聚合之外的状态传递给模型,而不是提取。

这可能意味着远程客户端需要提供数据,或者它可能意味着处理命令的应用程序获取所需的读取模型并提供答案。有许多不同的问题可以推动你在这里做出的选择

  • 如果客户端在生成命令时使用的读取模型与应用程序在处理命令时使用的视图有很大不同,则存在一些风险。
  • 保持稳定的API,您可以自由地重新设计模型中的聚合边界,而无需更新客户端。)

所以没有一个最好的答案,只需在不同的关注点之间进行权衡。

最近出现了后者的一个例子 - 如果你的商业模式要求某些命令需要特定用户的权限,那么我们就不应该从客户端获取面值的命令;我们需要应用程序验证命令发布者的身份,然后将该身份的表示传递给模型,以便它可以确定要采取的操作。

答案 1 :(得分:0)

@Edgars,

根据我的经验,您的命令处理程序可以"阅读"来自您的"只读数据阅读器的数据"。您用于模型的相同内容。

public class CreateNewSantaCommandHandler: ICommandHandler<CreateNewSantaCommand>
{
    public IReadOnlyRepo<SomeDTO> readOnlyRepo;
    public ISantaRepo<Santa> santaRepo;

    // Inject the repos in the constructor, etc. You get the idea.

    public void Execute(CreateNewSantaCommand command)
    {
        var suit = readOnlyRepo.GetSuit(command.suitType) //Data you need
        var santa = Santa.New(command); //Factory method;
        santa.GetDressedPlease(suit);
        santaRepo.Add(santa);
        santa.Save() // this shouldn't be here. Usually higher level. UOW.
    }
}

有意义吗?