查询端的投影主键应该是什么——CQRS、事件溯源、微服务
What should be projection primary key on query side - CQRS, Event Sourcing, Microservices
有一件事让我很困惑。
我有 2 个微服务。
一个创建命令,另一个使用命令并产生事件(事件存储在事件存储中)。
在我的示例中,聚合将 Guid 作为实体 ID,并且在创建聚合时创建 Guid。
让我感到困惑的是,该密钥(在写入端生成)是否应该通过事件传输到查询端(创建命令的微服务)?
或者查询端(投影)应该在读取数据库中有单独的 id。
或者我应该生成一些共享密钥?
最好的解决方案是什么?
我认为这取决于您的要求。使用不同的密钥是否有特定原因?
鉴于您使用 Guid 作为 PK,重用写入方分配的 PK 似乎最简单。
您可能希望保持密钥一致的一些原因:
在命令处理期间,一个 ID 返回给客户端,他们可能已经缓存了该 ID,并且应该合理地期望在查询读取端时能够使用该密钥。
如果你的写端数据是长期存在的,而你的读端输出有一个错误,如果你的键在写和读上保持一致,调试错误会容易得多边.
写入端的实体将使用另一个实体的写入端Guid PK作为其FK。当您为这个新的依赖实体发出事件时,您会希望读取端能够建立与主体的关系。
我认为这完全取决于您的设置。
如果您正在执行 CQRS,并且您有一个单独的读取服务(在相同的有界上下文中),那么读取端服务将根据需要对数据进行建模,或者重复使用相同的键与否。
如果您在两个不同的服务(单独的限界上下文)之间进行通信,那么我建议您在接收服务中创建新的主键并将传入键用作外键。就像处理 SQL 数据库中两个表之间的关系一样。
这个问题有点奇怪。
投影上的主键可以是任何字面意思,也可以没有。
这道题没有“正确答案”……全靠投影。
如果我的预测只是将与聚合相关的信息拉平怎么办...例如,我们有一个“订单”,我们为每个订单制作一行,显示有关该订单的摘要信息。在这里使用“OrderId”作为我的主键似乎有些意义。
如果我的预测是按产品计算订单数怎么办?那么使用“ProductItemId”会更有意义。
如果在这两种情况下,Id 本身(“OrderId”和“ProductItemId”)可能发生变化怎么办?那么使用另一个密钥可能很有意义。
如果这是一个仅追加的 table 怎么办?我可能连钥匙都不要。
同样,没有... 正确 ...在这里回答有很多情况,你可能运行 进入.
有一件事让我很困惑。 我有 2 个微服务。 一个创建命令,另一个使用命令并产生事件(事件存储在事件存储中)。
在我的示例中,聚合将 Guid 作为实体 ID,并且在创建聚合时创建 Guid。
让我感到困惑的是,该密钥(在写入端生成)是否应该通过事件传输到查询端(创建命令的微服务)? 或者查询端(投影)应该在读取数据库中有单独的 id。 或者我应该生成一些共享密钥?
最好的解决方案是什么?
我认为这取决于您的要求。使用不同的密钥是否有特定原因?
鉴于您使用 Guid 作为 PK,重用写入方分配的 PK 似乎最简单。
您可能希望保持密钥一致的一些原因:
在命令处理期间,一个 ID 返回给客户端,他们可能已经缓存了该 ID,并且应该合理地期望在查询读取端时能够使用该密钥。
如果你的写端数据是长期存在的,而你的读端输出有一个错误,如果你的键在写和读上保持一致,调试错误会容易得多边.
写入端的实体将使用另一个实体的写入端Guid PK作为其FK。当您为这个新的依赖实体发出事件时,您会希望读取端能够建立与主体的关系。
我认为这完全取决于您的设置。
如果您正在执行 CQRS,并且您有一个单独的读取服务(在相同的有界上下文中),那么读取端服务将根据需要对数据进行建模,或者重复使用相同的键与否。
如果您在两个不同的服务(单独的限界上下文)之间进行通信,那么我建议您在接收服务中创建新的主键并将传入键用作外键。就像处理 SQL 数据库中两个表之间的关系一样。
这个问题有点奇怪。
投影上的主键可以是任何字面意思,也可以没有。
这道题没有“正确答案”……全靠投影。
如果我的预测只是将与聚合相关的信息拉平怎么办...例如,我们有一个“订单”,我们为每个订单制作一行,显示有关该订单的摘要信息。在这里使用“OrderId”作为我的主键似乎有些意义。
如果我的预测是按产品计算订单数怎么办?那么使用“ProductItemId”会更有意义。
如果在这两种情况下,Id 本身(“OrderId”和“ProductItemId”)可能发生变化怎么办?那么使用另一个密钥可能很有意义。
如果这是一个仅追加的 table 怎么办?我可能连钥匙都不要。
同样,没有... 正确 ...在这里回答有很多情况,你可能运行 进入.