我想设置一个小型事件来源lib。 我在网上阅读了一些教程,到目前为止一切都已被理解。
唯一的问题是,在这些不同的教程中,有两种不同的数据库策略,但没有任何注释,为什么他们使用他们使用的那种。
所以,我想问你的意见。 重要的是,为什么您更喜欢您选择的解决方案。
解决方案是db结构,您可以在其中为每个事件创建一个表。
解决方案是db结构,您只创建一个通用表,并将事件作为序列化字符串保存到一列。
在这两种情况下,我都不确定他们如何处理事件更改,也许他们会创建一个全新的。
亲切的问候
答案 0 :(得分:33)
我建立了自己的事件采购库,我选择了选项2,这就是原因。
有一种说法可以说你可以在每个聚合上存储事件,但这取决于项目的要求。
我确实有一些关于如何使用事件流的帖子,您可能会觉得有用。
6 Code Smells With Your CQRS Events and How to Avoid Them
Aggregate Root – How to Build One for CQRS and Event Sourcing
How to Upgrade CQRS Events Without Busting Your Event Stream
我希望你觉得有用。
答案 1 :(得分:12)
解决方案是db结构,您只创建一个通用表,并将事件作为序列化字符串保存到一列
这是迄今为止最好的方法,因为重放事件更简单。现在我在事件采购方面的两分钱:这是一个很好的模式,但你应该小心,因为不是一切都像看起来那么简单。在我正在研究的系统中,我们保存了每个聚合的事件流,但我们仍然有一组规范化的表,因为我们无法接受为了获得对象的最新状态,我们必须运行所有事件(快照有帮助,但不是一个完美的解决方案)。因此,事件来源是一个很好的模式,它为您提供了完整的实体版本和完整的审计日志,它应该仅用于此,而不是作为一组规范化表的替代,但这只是我的两个美分。
答案 2 :(得分:4)
我认为最佳解决方案是使用#2 。如果您使用像mysql这样的事务性数据库,甚至可以同时将当前状态与相关事件一起保存。
我真的不喜欢并推荐解决方案#1 。
如果您对#1 的关注与事件版本控制/升级有关;然后为每个新变更声明一个新类。不要太懒惰;或者重复使用。让订阅者了解变化;给他们活动版。
如果您对#1 的概念与查询/解释事件有关;之后您可以随时轻松地将事件推送到nosqldb或eventstore(来自原始数据库)。
也;我用于事件源lib的模式是这样的:
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 { }
因此;使事件版本控制和升级显式;在域和代码库中。在部署新事件的来源之前,在订户中实施新事件的处理。和;如果不需要,不允许直接使用来自外部订户的域事件;放置一个集成层或类似的东西。
我希望我的想法对你有用。
答案 3 :(得分:2)
我读到了一个包含以下内容的事件采购方法:
基于你的用例:
一个。在聚合表上创建和注册,生成ID,版本= 0和事件类型,并在事件表上创建事件;
湾从聚合表中检索,按ID或事件类型检索事件,应用业务案例,然后更新聚合表(版本和事件类型),然后在事件表上创建事件。
虽然我这种方法更新聚合表上的某些字段,但它只将事件表保留为附加,并提高了性能,因为在聚合表中有最新版本的聚合。
答案 4 :(得分:0)
我会选择#2,如果你真的希望通过事件类型有一种有效的搜索方式,我只想在该列上添加一个索引。
答案 5 :(得分:0)
在此情况下,有两种策略可以访问有关主题的数据。 1)当前状态和2)事件排序。 在当前状态下,我们处理事件,但仅保留主题的最后状态。 通过事件排序,我们可以保留事件并在每次需要状态时通过处理事件来重建当前状态。 事件排序更可靠,因为我们可以跟踪导致当前状态发生的所有事件,但是绝对没有效率。避免中间状态(快照)不只是最后一个,这是常识,以避免始终重新处理所有事件。现在我们有了可靠性和性能。
在加密货币中有事件排序和本地快照-名称中的本地是因为分发了区块链并复制了数据。