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中执行一次验证已经发生。
在各种事件处理程序中,我需要访问每次从声明存储中检索数据所需的所有数据,并反复进行多次反序列化。
这对我来说似乎有点韵味。我是否应该在第一次检索文件时考虑缓存文件,并在所有事件处理程序完成工作后从缓存中清除它?
有人有更好的建议吗?
答案 0 :(得分:1)
根据我对您的问题的理解,问题实际上是:&#34;我应该使用缓存机制来阅读验证处理程序上的claim store
吗?&#34;
在您的情况下,因为claim store
中的数据是不可变的,所以只要您需要它就可以缓存它。这就是不可变数据的美妙之处:永远可缓存。
要实现缓存机制,您可以在claim store
上使用装饰器模式,并切换到composition root
中dependency container
中的缓存版本。通过这种方式,您可以随时切换回未缓存的文件。
你可以更多地缓存它,如果验证的数据不会改变并且随着时间的推移而重复,你甚至可以缓存验证的结果。