Nservicebus 有条件地开始传奇

Nservicebus 有条件地开始传奇,nservicebus,saga,Nservicebus,Saga,我有两种类型的活动: 人事变动 PersonalAddressChanged 当一个新的人(和一个新的地址)被创建(创建或更新)时,它们也会被发布 创建一个新人时,会发布两个事件:PersonChanged和PersonalAddressChanged(按顺序)。但是,由于NServiceBus是异步的,因此可以按任何顺序处理它们。当一个地址被改变时(对于一个现有的人),没有PersonChanged事件,只有PersonalAddressChanged事件 我想为PersonalAddre

我有两种类型的活动:

  • 人事变动
  • PersonalAddressChanged
当一个新的人(和一个新的地址)被创建(创建或更新)时,它们也会被发布

创建一个新人时,会发布两个事件:PersonChanged和PersonalAddressChanged(按顺序)。但是,由于
NServiceBus
是异步的,因此可以按任何顺序处理它们。当一个地址被改变时(对于一个现有的人),没有PersonChanged事件,只有PersonalAddressChanged事件

我想为PersonalAddressChanged事件编写一个处理程序,它将:

  • 检查此人是否在数据库中
  • 如果是,则只需进行更新
  • 如果没有,那么开始传奇故事,等待人事变动事件(假设是一个新人)
  • 在PersonChanged事件中,我需要将person插入数据库,找到这个传说,并再次运行PersonalAddressChanged的处理程序

    我可以通过NServiceBus传奇实现这一点吗?我不能假设消息处理应该是有序的
    personchange→ PersonalAddressChanged
    ,因为有时任何特定的地址更改都不会发生PersonChanged事件。

    您可以通过sagas实现这一点,是的,尽管您可能不应该这样做。首先,在创建和更新人员时使用相同的事件会丢失事件中的语义信息(您正试图通过检查数据库中的用户来重新创建语义信息)。你还将自己暴露在许多潜在的比赛条件下,需要考虑如何应对这些条件。我的建议是修改您的消息流,这可能会消除您当前的问题

    但是,如果您想尝试它,您可以这样做:(没有测试或编译,只是概念代码)

    公共类MySaga:Saga,IAmStartedByMessage,IAmStartedByMessage{
    公共覆盖无效配置HowtoFindsaga(){
    //如何关联PersonChanged和PersonalAddressChanged消息
    }
    公共无效句柄(PersonChanged消息){
    插入(味精);
    if(Data.PendingAddressChange!=null)
    更新数据库(msg);
    MarkAsComplete();
    }
    公共无效句柄(PersonalAddressChanged消息){
    if(信息数据库(信息人)){
    更新数据库(msg);
    MarkAsComplete();
    }
    否则{
    Data.PendingAddressChange=msg;
    }
    }
    }
    公共类MySagaDataType:IContainSagaData{
    PublicPersonalAddressChanged PendingAddressChange{get;set;}
    }
    
    我同意@carlpett关于重新思考活动的一些语义的说法

    我也建议你在这里考虑一个不同的解决方案。
    如果你的PersonalAddressChanged消息处理程序看到数据库中没有当前的人,就用它得到的地址创建一个呢?

    如果
    PersonalAddressChanged
    事件只针对一个现有的人发送,我根本不会为sagas操心

    相反,我会依赖重试逻辑来处理无序到达的消息

    无论何时处理
    PersonalAddressChanged
    ,它都可以假定存在个人记录。如果没有,则处理程序抛出异常,稍后重试


    当它再次被加工时,
    PersonChanged
    事件已被处理,一切正常。

    我喜欢此解决方案,但我遇到以下错误:
    NHibernate.event.Default.AbstractFlushingEventListener-无法将数据库状态与会话NHibernate.PropertyValueException同步:错误:为Namespace.PersonSaga.PendingAddressChanged-->System.IndexOutOfRangeException:此SqlParameterCollection的索引29无效,计数为29
    。有什么想法吗?@bpiec:您的事件是作为接口还是具体类实现的?NServiceBus围绕接口生成代理类,这可能是NHibernate不喜欢的。尝试用该类的内容替换
    PersonalAddressChanged
    属性(即如果
    类PersonalAddressChanged{public string Address{get;set;}public Guid PersonId{get;set;}
    ,则将这两个参数移到
    MySagaDataType
    中并分别设置)我在我的Saga类中添加了几个属性,每个属性都包含相同名称的属性,NSB在SQL Server中生成了错误的表,因此无法持久保存Saga:(没关系,我会尝试找到一个解决办法,但答案是我一直在寻找的!事实上,我有单独的添加和更改事件,但我不能假设当更改地址时,我在数据库中已经有一个人…我无法创建一个新的人,它必须通过验证,并且需要一些字段。然后@chrisbednarski的答案就是我想要的建议。