发送命令后更新界面

9

我正在为解决架构问题而苦恼, 我们的系统使用NService Bus,使用NEventStore和NES实现DDD和事件源。 客户端应用程序是WPF

我仍然无法决定更新UI的最佳实践, 例如: 我有一个UI来创建(批次{Id,开始日期,结束日期等}),用户点击保存后,我发送一个命令(CreateBatch)。

Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc });

现在, 选项一
我是否应该以以下方式注册以获得回复:
private void btnSave_Click(object sender,EventsArg e){
    Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc })
       .Register<int>(c=> { 
                     MessageBox.Show("Command Succeded");
                     Close();});
}

在服务器端:

public void Hanlde(CreateBatch cmd){
   //initiate aggregate and save it.
   Bus.Return( /*What ?? Success Code?*/);
}

在这种情况下,如何处理错误?(例如验证错误,例如在同一日期已经有一个批次开始了?),因为您只能返回int或string!! 选项#2: 发送命令,关闭窗口,假装记录已添加到主网格中,直到用户刷新网格并从ReadModel数据库中获取真实记录,或者发现记录尚未添加且没有任何线索!
private void btnSave_Click(object sender,EventsArg e){
    Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc });
    Close();
}

选项#3


发送命令,关闭窗口,虚假地将记录添加到主网格中但标记为(正在进行),等待(BatchCreated)事件到来,检查它是否与之前发送的批次id相同,然后在网格中标记记录为已持久化。

private void btnSave_Click(object sender,EventsArg e){
    Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc });
    Close();
}


public class BatchHandler : IHandleMessages<BatchCreated>
{
    public void Handle(BatchCreated evnt)
    {
     if(SomeCachForSentIDS.Contains(evnt.BatchId)
         ///Code to refresh the row in the grid and reflect that the command succeeded.
    }
}

如果您有更好的选择,或对提到的选项有建议,甚至有关于如何处理这种情况的链接,我将不胜感激。
谢谢。

实际上,这取决于它们不可接受的意义!如果是愚弄用户的意义,我见过很多人(包括Udi Dahan)都认为选项2是一个好选择,他们称之为“欺骗用户”!至于选项3,我仍然无法确定是否使用! - Nour
如果您(就像Udi所说的那样)将用户界面设置为预期状态,那么这并不是欺骗。通常情况下,命令应该很少失败。 - Gope
另一件需要考虑的事情是,您是否需要立即将它们带到数据网格视图?如果这是工作流程的一部分,您可以转到下一步并避免使用网格。 - Adam Fyles
@AdamFyles 假设我可以避免使用网格,但如果出现错误,命令执行失败怎么办?如果用户正在等待批处理被创建以便开始填充它,该怎么办? - Nour
2个回答

7
在像这样的解决方案中引入消息传递时,一个重要的原则是确保命令几乎不会失败(正如@Gope在评论中提到的那样)。
这意味着在发送消息之前应该在客户端执行各种验证检查。
现在,即使进行了客户端验证,您仍然可能面临竞争条件-2个用户同时创建批处理,在某些方面发生冲突。处理此问题的方法是寻求澄清用户意图,可能还要更改任务性质以及UI,从而使新命令即使在并行处理的情况下也能成功。
作为解决方案的简单尝试,您可以重新定义逻辑,为批次引入新状态-例如“冲突”,如果另一个批次同时开始,则设置该状态。这样,命令就成功了(批次已经创建),然后您可以使用类似SignalR的东西向用户推送此状态的通知,以便他们进行更正。
最后,您可能需要重新考虑是否完全使用消息传递,并转向简单的2层同步解决方案。每种方法都有其适用的时间和场合。

1
如何为异步消息设计这些用户界面(特别是在我们被灌输了CRUD思维方式之后)是这些系统中的百万美元问题。
我完全同意Udi的评估。此外,您的问题似乎对确切的业务要求非常不透明,但CreateBatch命令和BatchCreated事件名称的CRUD性质让我想知道使用消息传递是否真的有用。
如果您发现自己必须等待CreateBatch完成才能对其进行更多操作,那么也许根本就不应该有CreateBatch。也许您只应该“本地”创建某些东西(这可能意味着在JavaScript中的客户端端,或者像Udi建议的那样,在最简单的2层数据库模型中),然后发送一个命令以完成所有工作(例如ProcessBatch)。
毕竟,消息传递的目标不是完全将Web层与向数据库发出请求分离。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接