如何使用cqrs

时间:2017-03-29 14:27:10

标签: c# cqrs rebus

TL; DR:  我在制作反模式吗?  2.使用CQRS处理索赔检查的最佳方法是什么?

我的系统中有几个入口点(webapi传入json和xml),以及带有固定长度文件的文件系统。

我正在使用Rebus与MSMQ和Sql server来管理我的消息。数据可能大于4mb(如果我相信,MSMQ&#39s的最大消息大小)。当系统收到文件时,我将其转换为流并创建一个实现IAttachmentCommand的命令,如下所示:

public interface IAttachmentCommand : ICommand
{
    Stream Attachment { get; }

    IClaimCheckCommand ToClaimCheck(string attachmentId);
}

public interface IClaimCheckCommand : ICommand
{
    string AttachmentId { get; }
}

然后我使用命令总线(使用Rebus)发送它。如果命令是IAttachmentCommand类型,我在rebus databus表中创建一个附件,并在原始命令上使用ToClaimCheck返回一个新的IAttachmentCommand。 AttachmentCommand实际上是原始命令的副本,除了它现在有attachmentId而不是数据。

然后我将使用我的新AttachmentId在我的Rebus总线中调用send,如下所示:

public void Send<TCommand>(TCommand command) where TCommand : ICommand
{
  if (command is IAttachmentCommand)
  {
    var cmd = command as IAttachmentCommand;
    var task = CreateAttachment(cmd);  // method excluded, but persists to Rebus DataBus and returns AttachmentId
    var claimCheck = task.Result;
    _activator.Bus.Send(claimCheck);
  }
  else
  {
    _activator.Bus.Send(command);
  }
}

这似乎有效,尽管我很高兴将我的代码拉到碎片。我可以发送命令,应用由我的聚合根生成的事件,持久存储到事件存储等等。

我只是从webapi调用或文件系统中选取一个文件,创建一个命令并使用我的命令总线将其发送出去。

在单独的Windows服务中,我有一个命令调度程序监视这些消息的MSMQ。当一条消息进来时,它会遍历许多CommandValidationHandlers来验证命令。 CommandValidationHandlers实现以下内容:

public interface ICommandValidationHandler<in TCommand> where TCommand : ICommand
{
   ValidationResult Validate(TCommand command);
}

ValidationResult有效地返回错误集合。记录这些错误,发布为包含命令信息和错误的InvalidCommand事件 - 这允许我让任何正在侦听的订阅者接收事件 - 发送邮件或调用Web服务等来说明邮件失败,原因。如果该命令无效,则抛出异常并且该过程停止。

我担心的是,在验证时我有attachmentId,并且必须检索文件,然后验证该文件,例如对xsd进行验证。

从那里我需要将它反序列化为一个对象(通常是一个包含元数据的金融交易的集合,例如没有交易等),并对对象中的数据执行额外的验证。

完成此验证后,我需要遍历对象中的事务集合,并使用命令总线将这些事务发送到相关的有界上下文,并进行进一步处理。

在这种情况下,我似乎会多次访问声明存储区 - 每个验证处理程序一次(虽然我猜这可以通过复合的验证器集合来解决),但是再次在Command Handler中执行一次验证已经发生。

在各种事件处理程序中,我需要访问每次从声明存储中检索数据所需的所有数据,并反复进行多次反序列化。

这对我来说似乎有点韵味。我是否应该在第一次检索文件时考虑缓存文件,并在所有事件处理程序完成工作后从缓存中清除它?

有人有更好的建议吗?

1 个答案:

答案 0 :(得分:1)

根据我对您的问题的理解,问题实际上是:&#34;我应该使用缓存机制来阅读验证处理程序上的claim store吗?&#34;

在您的情况下,因为claim store中的数据是不可变的,所以只要您需要它就可以缓存它。这就是不可变数据的美妙之处:永远可缓存。

要实现缓存机制,您可以在claim store上使用装饰器模式,并切换到composition rootdependency container中的缓存版本。通过这种方式,您可以随时切换回未缓存的文件。

你可以更多地缓存它,如果验证的数据不会改变并且随着时间的推移而重复,你甚至可以缓存验证的结果。