发送命令后更新UI
本文关键字:更新 UI 命令 | 更新日期: 2023-09-27 18:05:15
我正在努力解决这个架构问题,我们的系统使用NService总线,并使用NEventStore和NES实现DDD和EventSourcing。客户端应用程序是WPF
我仍然不能决定什么是更新UI的最佳实践,例如:我有一个UI来创建(Batch {Id, StartDate, EndDate等}),在用户点击保存后,我发送一个命令(CreateBatch),
Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc });
现在选项# 1
我是否应该按照以下方式登记回复?
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.
}
}
如果你有任何更好的选择,或者对上述选项有建议,甚至是一些关于如何处理这种情况的链接,我将不胜感激。
谢谢。
在这样的解决方案中引入消息传递时,一个重要的原则是确保命令几乎不会失败(正如评论中提到的@ ope)。
这意味着在发送消息之前,应该在客户端执行所有类型的验证检查。
现在,即使在执行客户端验证时,您仍然可能暴露于竞争条件—两个用户同时创建一个批处理,这些批处理以某种方式相互冲突。处理这个问题的方法是澄清用户意图,可能会改变任务的性质以及UI,使新命令即使在并行处理的情况下也能成功。
作为解决方案的一个简单尝试,您可以重新定义逻辑以为批处理引入一个新状态-例如"冲突",如果另一个批处理同时启动,则将设置该状态。这样命令就成功了(创建了批处理),然后使用SignalR之类的东西将此状态的通知推回给用户,以便他们可以着手纠正它。
最后,您可能需要完全重新考虑消息传递的使用,而只使用简单的两层同步解决方案。
如何为异步消息传递设计这些用户界面(特别是在我们被灌输了CRUD思维方式之后)是这些系统中最重要的问题。
我100%同意Udi的评估。此外,您的问题似乎对确切的业务需求相当不透明,但是CreateBatch命令和BatchCreated事件名称的CRUD性质使我怀疑它是否真的是与消息传递有关的有用的事情。
如果你发现自己在一个情况下,你必须等待CreateBatch完成,所以你可以对它做更多的事情,也许你不应该有CreateBatch。也许你应该只是在"本地"创建一些东西(这可能意味着JavaScript中的客户端,或者像Udi建议的那样,在最简单的2层数据库模型中),然后发送一个命令来做真正的工作(ProcessBatch也许?)一旦一切完成。
毕竟,消息传递的目标并不是将web层与数据库请求完全分离。