4

我们正处于开发周期(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;
    }
}

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

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

    public OrderSubmittedEvent_V1(int orderId)
    {
        OrderId = orderId;
    }
}

并引入另一个与我的原始事件同名但添加了属性的事件,就像这样

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; }
}

我仍然必须继续更改发布此事件的代码以包含新属性的值。

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

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

大家怎么看这种做法?

下一个待办事项

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

谢谢

4

5 回答 5

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; }
}

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

此外,您需要注意您永远不会删除任何旧的事件类,因此我将它们装饰为过时的,以让其他开发人员知道不要使用该事件。

于 2013-05-13T15:45:48.700 回答
4

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

于 2013-05-14T05:17:00.167 回答
1

诚然,我没有机会尝试以下方法,但我想从第一天开始就进行版本控制:

由于完整的类型名称是相关的,我会选择名称空间。

namespace Primary.Messages.V1
{
    public class CompanyCreated
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }
}

namespace Primary.Messages.V2
{
    public class CompanyCreated
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string TaxNumber { get; set; }
    }
}

这些可能位于不同的程序集中,您可以将较旧的程序标记为已过时(如 Sarmaad 建议的那样)。可能旧版本不一定已经过时。

有任何想法吗?

于 2013-05-15T04:54:27.043 回答
1

我会谨慎混合事件和命令。他们有不同的目的,解决不同的问题。

为了更好地理解我的意思,可以这样想 命令更像 RESTful API,客户端-服务器通信。而事件溯源更多的是一种存储数据的方式。

两者都需要版本控制作为通过不变性提供向后兼容性的一种方式,但再次出于不同的原因。因此,实现和例外是不同的。

我肯定会推荐Greg Young 写的一本书 Event Versioning来深入了解事件源系统的版本控制。

有关命令的更多信息,请查看CQRS 系列,尤其是通过 HTTP 的 CQRS

于 2020-08-26T06:05:11.830 回答
1

在考虑为什么需要按照问题的方式进行事件版本控制,更具体地说是在答案中建议的方式时,我完全没有理由?

我只能想到两个用例

1- 当前使用的事件类已弃用,不再需要。然后可以随时在 git 中跟踪该类。那么,为什么要通过保留死类来打扰和复杂化活动代码呢?

2-业务需求发生了变化,现在您需要保留基本事件,但您还需要另一个类似的事件,但有一些参数差异。这可以通过多种方式解决,比如装饰器模式可以在很大程度上帮助处理这种变化。或者,新事件可能代表一个独特的领域概念,而不是试图将这个概念强加到现有模型中,它可能会更好更语义化地命名它并以这种方式使用它。

于 2017-10-31T04:27:38.467 回答