CQRS中的事件版本控制

nes*_*h_s 4 versioning events domain-driven-design cqrs

我们处于开发周期的一个阶段(asp.net mvc applciation),我们需要对现有的命令和事件进行更改(比如添加/删除一些属性等).

我一直在努力寻找一种在系统中引入命令/事件版本控制的方法.我已经在google/stackoverflow等上阅读了很多帖子,但我还是要看一个实现它的代码示例.在版本控制时是否应该遵循推荐的模式.如果是,任何示例/片段?

编辑:这是我有多远

  1. 我已经向后版本化了我的事件,这样最新的事件将始终被称为相同,而过时的事件将添加一个后缀,如'_V1','_ V2'等.

所以如果我有一个活动

public class OrderSubmittedEvent : IDomainEvent
{
    public int OrderId { get; private set; }

    public OrderSubmittedEvent(int orderId)
    {
        OrderId = orderId;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我必须添加一些属性,我将上面的事件重命名为

public class OrderSubmittedEvent_V1 : IDomainEvent
{
    public int OrderId { get; private set; }

    public OrderSubmittedEvent_V1(int orderId)
    {
        OrderId = orderId;
    }
}
Run Code Online (Sandbox Code Playgroud)

并引入另一个与我的原始事件同名的事件,但添加了属性,如此

public class OrderSubmittedEvent : IDomainEvent
{
    public int OrderId { get; private set; }

    public OrderSubmittedEvent(int version = 1, int orderId = 0, string customerName =  
                               "Joe blogs", string address = "Earth")
    {
        OrderId = orderId;
        CustomerName = customerName;
        Address = address;
        CurrentVersion = version;
    }

    public static int LatestVersion
    {
        get { return 2; }
    }

    public int CurrentVersion { get; set; }

    public string CustomerName { get; set; }
    public string Address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我仍然需要继续更改发布此事件的代码以包含新属性的值.

  1. 任何给定的时间点,当我从事件存储中获取所有事件(例如,用于重放)时,在反序列化(在本例中为OrderSubmittedEvent)后,它们将始终具有相同的类型,其中新属性不是填充的旧事件的一部分他们的默认值.

在重播我的事件时,我让我的事件通过IEventUpgrader这首先验证事件是否是可用的最新版本.由于类型将始终是事件类型,因此此检查基于属性"LatestVersion"和"CurrentVersion"

每个人都会想到这种方法?

下一个待办事项

  1. 如果事件是旧版本,则发布"UpdateMYEVENT"事件

谢谢

Sar*_*aad 8

通常您只需要对事件进行版本控制,您可以忽略这些命令,因为您不将它们存储在事件存储中.

实现版本控制的方法很少..我的方法很简单:

[Obsolete]
public class CompanyCreated
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

public class CompanyCreated_V2
{
    public Guid Id { get; set; }
    public string CompanyName { get; set; }
    public string TaxNumber { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在从事件存储中读取事件时,您需要处理从旧事件到新事件的转换.

另外,你需要知道你永远不会删除任何旧的事件类,因此我将它们装饰为Obsolete,让其他开发人员知道不要使用该事件.


Tom*_*Tom 5

如果您仅添加和删除属性,则可能不需要对事件进行版本控制;只需忽略已删除的序列化属性,并为您添加的属性使用合理的默认值。