重用NServiceBus消息传奇数据

Sea*_*ron 2 nservicebus

有没有理由不在IMessagesaga数据中重用NServiceBus消息()?我的意思是有这样的消息:

public class Order : IMessage
{
   public virtual List<TillOrderLine> OrderLines { get; set; }
}

public class TillOrderLine : IMessage { ... }
Run Code Online (Sandbox Code Playgroud)

然后在像这样的传奇和传奇数据中使用它:

public class OrderProcessingSaga : 
    Saga<OrderProcessingSagaData>, 
    IAmStartedByMessages<Order> { ... }

public class OrderProcessingSagaData : ISagaEntity
{
   public virtual Guid Id { get; set; }
   public virtual string Originator { get; set; }
   public virtual string OriginalMessageId { get; set; }

   // The message data is stored by the saga here.
   public virtual Order Order { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我意识到消息是由传输层(MSMQ)存储的,而传奇数据是通过saga持久保存到DB的.它适用于我当前的用例,并且重用该类似乎更优雅,而不是为消息创建一个,而为saga存储创建另一个.

我想知道这种方法是否有任何陷阱?

Dav*_*ike 6

我同意mookid8000所说的一切,但我还有一个细节需要补充.

您的传奇存储通常会有很多争用.为了保证一致性,传奇存储提供程序通常会对数据进行更新锁定,以保证来自同一传奇的另一条消息不会同时改变状态.

如果你使用默认的NHibernate saga persister(并且你的虚拟属性告诉我你是),那么NHibernate会使用一些假设来保存你的数据:

  • 您的saga数据中的复杂类型将导致遵循ComplexTypePropName_ChildPropertyName语法(或其附近的数据库列 - 在此处从内存操作).因此,您的传奇数据仍将包含在一个表中的1行内.
  • 如果你的saga数据中有一个列表,它显然必须创建一个新表来存储列表项.现在,您的saga数据包含在一个主行和多个详细信息行中.
    • 为了让NHibernate映射它,你的集合类型还必须有一个名为Id的Guid属性,这意味着你不能存储基元列表,而你的TillOrderLine类(公共消息的一部分)将需要这个Id属性,它不会了解您的服务的商业目的.
  • 如果你的saga数据中有一个复杂的类型(Order,基本上是重用的消息),我不知道你的情况会发生什么,它本身包含一个列表(TillOrderLines).

在任何情况下,更多表中需要更多行来分割数据所需的saga persister,使用粒度行锁锁定所涉及的行的难度就越大.有足够的争用,行锁将开始升级到页锁和表锁,然后你真的遇到了问题.

这就是为什么文档数据库真的会为saga存储发光,这就是为什么在NServiceBus 3.0中他们将RavenDB作为默认的saga persister.

在此之前,请看一下我编写的基于XML序列化的Saga Persister,它可以为即将推出的RavenDB风格的saga persister带来一些好处.

如果你必须坚持使用NHibernate,我强烈建议你不要将你的消息与你的saga持久性解决方案紧密地结合起来.我差点保证会回来困扰你.