如何使用Eventflow读取.NET 6应用中EventEntity表的事件?
Eventflow读取EventEntity表的解决方案
直接读取EventEntity表的方法
EventEntity是Eventflow默认事件存储(如SQL实现)的内部表,你可以通过EF Core直接映射该表进行查询,步骤如下:
- 定义与数据库表结构匹配的实体类:
public class EventEntity { public Guid Id { get; set; } public Guid AggregateId { get; set; } public string AggregateName { get; set; } public int AggregateVersion { get; set; } public string EventName { get; set; } public byte[] EventData { get; set; } public DateTimeOffset Timestamp { get; set; } // 补充表中其他字段 } - 在你的DbContext中配置DbSet并映射表名:
public class AppDbContext : DbContext { public DbSet<EventEntity> EventEntities { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<EventEntity>(e => { e.ToTable("EventEntity"); e.HasKey(x => x.Id); // 根据实际表结构配置字段映射、索引等 }); } } - 执行查询操作:
var targetAggregateId = Guid.Parse("目标聚合根ID"); var events = await dbContext.EventEntities .Where(e => e.AggregateId == targetAggregateId) .OrderBy(e => e.AggregateVersion) .ToListAsync();
注意:此方式属于直接操作Eventflow内部存储,禁止修改表中数据,否则会破坏事件溯源的完整性。
是否可以为EventEntity创建ReadModel?
不建议直接为EventEntity创建ReadModel。原因是:
- ReadModel在Eventflow中的设计定位是处理领域事件、生成面向查询的投影视图,而EventEntity本身是原始事件的持久化载体,并非业务意义上的领域模型。
- 正确的做法是基于具体的领域事件创建ReadModel,通过Eventflow的订阅机制自动更新视图,示例如下:
public class OrderReadModel : IReadModel, IAmReadModelFor<OrderAggregate, OrderId, OrderCreatedEvent> { public Guid Id { get; set; } public string OrderNumber { get; set; } public DateTime CreatedAt { get; set; } public void Apply(IReadModelContext context, IDomainEvent<OrderAggregate, OrderId, OrderCreatedEvent> domainEvent) { Id = domainEvent.AggregateId.Value; OrderNumber = domainEvent.Event.OrderNumber; CreatedAt = domainEvent.Event.CreatedAt; } }
注册该ReadModel后,Eventflow会自动捕获对应领域事件并更新ReadModel数据,既符合框架设计理念,也能保证数据一致性。
使用Eventflow内置API读取事件
Eventflow提供了IEventStore接口,可直接读取指定聚合根的事件,这是更符合框架设计的方式,无需直接操作数据库表:
public class AggregateEventReader { private readonly IEventStore _eventStore; public AggregateEventReader(IEventStore eventStore) { _eventStore = eventStore; } public async Task<IReadOnlyCollection<IDomainEvent>> GetAggregateEventsAsync(Guid aggregateId, Type aggregateType) { // 构建聚合根ID对象 var aggregateIdInstance = Activator.CreateInstance( aggregateType.GetNestedType("Id"), aggregateId); if (aggregateIdInstance == null) throw new ArgumentException("无效的聚合根类型"); // 加载聚合根的所有事件 var eventStream = await _eventStore.LoadEventsAsync( aggregateType, aggregateIdInstance, CancellationToken.None); return eventStream.Select(e => e.DomainEvent).ToList(); } }
此方式会自动处理事件的反序列化,直接返回领域事件对象,无需手动解析EventData字段。
内容的提问来源于stack exchange,提问作者Maxime Dousselaere
相关产品推荐
相关产品推荐

