EventStoreDB客户端连接和流写入必须用EventData包装事件,直接序列化领域对象会丢失类型元数据;EventType须与类名严格一致,ContentType推荐ApplicationJson;聚合根ID必须作为流名;ExpectedVersion需按场景选NoStream或StreamExists;重建状态须按EventNumber升序消费事件;快照为刚性需求,应存于独立流并写时触发。

EventStoreDB 客户端连接和流写入必须用 EventData 包装事件
直接序列化领域对象进 EventStore 会丢失类型元数据,导致读取时无法还原为原始类。EventStoreDB 不自动识别 .NET 类型,必须显式指定 EventType 和 EventData 的 ContentType(推荐 ApplicationJson)。
- 写入前用
System.Text.Json序列化事件对象,再构造EventData,EventType字符串要与领域事件类名严格一致(如"OrderPlaced") - 避免用
Binary内容类型——调试困难、跨语言不友好、无法被 ESDB 的投影(Projection)解析 - 聚合根 ID 必须作为流名(stream name),例如
"order-123",不能全用"all"流——否则重建状态时无法按聚合边界隔离 - 写入失败常见原因是
ExpectedVersion不匹配:首次写用ExpectedVersion.NoStream,追加用ExpectedVersion.StreamExists或具体版本号
重建聚合根状态时,ReadStreamAsync 必须按版本顺序消费事件
事件顺序就是状态演化顺序,跳过、乱序或重复应用都会导致聚合根处于非法状态。EventStoreDB 保证单个流内事件的严格递增版本号(EventNumber),但不保证全局时间顺序。
- 调用
ReadStreamAsync("order-123", StreamPosition.Start, maxCount: int.MaxValue)获取全部历史事件,不要分页漏读 - 遍历结果时必须按
ResolvedEvent.Event.EventNumber升序处理——虽然返回默认有序,但显式排序更安全(尤其测试 mock 数据时) - 每个事件反序列化后,应调用聚合根的
Apply(事件实例)方法(非 public setter),确保状态变更逻辑集中且不可绕过 - 警惕空事件体:
ResolvedEvent.Event.Data.Length == 0表示软删除或元事件,需跳过或特殊处理
快照(Snapshot)不是可选优化,而是重建性能瓶颈的刚性解法
当一个聚合流积累上千事件后,每次重建都要重放全部事件,延迟从毫秒级升至秒级。EventStoreDB 本身不提供快照存储,必须自行实现。
- 快照应写入独立流,如
"order-123-snapshot",事件类型为"AggregateSnapshot",数据体包含聚合根当前状态 + 最后应用的事件版本号(SnapshotVersion) - 重建时先查快照流:
ReadStreamAsync("order-123-snapshot", StreamPosition.End, maxCount: 1),若有结果,则从该版本号+1开始读原事件流 - 快照更新策略建议“写时触发”:每次成功写入新事件后,若
当前事件版本 % 100 == 0,就生成并写入新快照——避免定时任务遗漏或重复 - 快照数据必须只含可序列化字段,禁止包含
Action、EventHandler等运行时引用
AggregateRoot 基类的设计关键在隔离“变更逻辑”和“事件发布”
领域模型不该感知 EventStoreDB,聚合根内部不应出现 EventStoreConnection 或 StreamWriter。事件发布必须延迟到业务事务提交后,否则可能产生“已发事件但业务回滚”的不一致。
- 聚合根基类维护
private readonly List,所有Apply()同时向其中添加事件实例 - 业务方法(如
ConfirmPayment())只调用Apply(new PaymentConfirmed(...)),不直接发事件 - 仓储(Repository)负责从聚合根提取
_uncommittedEvents,批量写入 EventStore,并在成功后调用ClearUncommittedEvents() - 切勿在
Apply()里做 I/O、HTTP 调用或锁操作——它必须是纯内存、快速、无副作用的
EventStore 的版本控制和流边界是硬约束,不是配置选项;快照时机和聚合根的事件收集方式,决定了系统能否撑过百万级事件规模。这两处一旦设计偏移,后期几乎无法低成本修正。










