最佳事件采购数据库战略

Sha*_*iZy 28 database cqrs event-sourcing

我想设置一个小型的事件采购库.我在网上阅读了一些教程,到目前为止一切都被理解了.

唯一的问题是,在这些不同的教程中,有两种不同的数据库策略,但没有任何注释,为什么他们使用他们使用的那个.

所以,我想问你的意见.重要的是,为什么您更喜欢您选择的解决方案.

  1. 解决方案是db结构,您可以在其中为每个事件创建一个表.

  2. 解决方案是db结构,您只需创建一个通用表,并将事件作为序列化字符串保存到一列.

在这两种情况下,我都不确定它们如何处理事件更改,也许它们会创建一个全新的事件.

亲切的问候

Cod*_*ler 35

我建立了自己的事件采购库,我选择了选项2,这就是原因.

  • 您可以通过聚合ID而不是事件类型来查询事件流.
  • 如果事件全部在不同的表中,则按顺序重现事件将是一种痛苦
  • 这会使升级事件变得有点痛苦

有一种说法可以说你可以在每个聚合上存储事件,但这取决于项目的要求.

我确实有一些关于如何使用事件流的帖子,你可能会觉得有用.

6代码闻到您的CQRS事件以及如何避免它们

聚合根 - 如何为CQRS和事件采购构建一个

如何在不破坏事件流的情况下升级CQRS事件

我希望你觉得有用.


MeT*_*tus 13

解决方案是db结构,您只需创建一个通用表,并将事件作为序列化字符串保存到一列

这是迄今为止最好的方法,因为重放事件更简单.现在我在事件采购方面的两分钱:这是一个很好的模式,但你应该小心,因为不是一切都像看起来那么简单.在我正在研究的系统中,我们保存了每个聚合的事件流,但是我们仍然有一组规范化的表,因为我们无法接受为了获得对象的最新状态,我们必须运行所有事件(快照有帮助,但不是一个完美的解决方案).因此,事件来源是一个很好的模式,它为您提供了完整的实体版本和完整的审计日志,它应该仅用于此,而不是作为一组规范化表的替代,但这只是我的两个美分.

  • 保持实体的最新(最终一致)视图与事件源不相容,实际上它经常一起使用.事件采购只是意味着事件是您数据的唯一权威来源,因此您的物化视图/投影必须从中派生出来.将视图视为一种便利,可以随时进行破坏/重建,并且你很好. (5认同)
  • 刚刚完成你的答案,不需要粗鲁:) (4认同)
  • 实际上,这只是进行CQRS的一种方式,CQRS的设计理念是,在许多情况下,每次构建纯事件都可能效率低下. (2认同)

Saf*_*soy 6

我认为最好的解决方案是使用#2。如果您使用像 mysql 这样的事务数据库,您甚至可以同时将当前状态与相关事件一起保存。

我真的不喜欢并推荐解决方案#1

如果您对#1的关注是关于事件版本控制/升级;然后为每个新更改声明一个新类。不要太懒;或者沉迷于重用。让订阅者知道变化;给他们事件版本。

如果您对#1的顾虑是关于查询/解释事件;然后您可以随时轻松地将您的事件推送到 nosqldb 或 eventstore(来自原始数据库)。

还; 我用于事件源库的模式是这样的:

public interface IUserCreated : IEventModel
{

}

public class UserCreatedV1 : IUserCreated
{
    public string Email { get; set; }
    public string Password { get; set; }
}

public class UserCreatedV2 : IUserCreated
{
    // Fullname added to user creation. Wrt issue: OA-143

    public string Email { get; set; }
    public string Password { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class EventRecord<T> where T : IEventModel
{
    public string SessionId { get; set; } // Can be set in emitter.
    public string RequestId { get; set; } // Can be set in emitter.
    public DateTime CreatedDate { get; set; } // Can be set in emitter.
    public string EventName { get; set; } // Extract from class or interface name.
    public string EventVersion { get; set; } // Extract from class name
    public T EventModel { get; set; } // Can be set in emitter.
}

public interface IEventModel { }
Run Code Online (Sandbox Code Playgroud)

所以; 使事件版本控制和升级明确;在域和代码库中。在部署新事件的来源之前,在订阅者中实现对新事件的处理。和; 如果不需要,则不允许直接使用来自外部订阅者的域事件;放置一个集成层或类似的东西。

我希望我的想法对你有用。