EventFlow

2025-12-07 0 809

EventFlow

$ dotnet add package EventFlow

EventFlow是一个基本的CQRS+ES框架,旨在易于使用

看看我们的入门指南,DO和NOTS和FAQ。

或者,加入我们的Discord服务器与社区互动。希望它可以重新启动,以启动即将发布的V1发行。

特征

  • 易于使用:设计具有明智的默认和实现,使创建示例应用程序变得容易
  • 高度可配置和可扩展: EventFlow使用其核心每个部分的接口,从而易于使用自定义实现替换或扩展现有功能
  • 不使用线程或背景工人
  • 麻省理工学院许可易于理解和使用企业许可证

版本

1.0版的开发已经开始,并且主要是针对与Microsoft扩展抽象(主要是IserviceProvider和ilogger <>)替换EventFlow类型相关的更改的制动更改。

以下每个版本及其相关分支的关键特征(尚未正确配置)。

  • 1.x

    表示EventFlow的下一个迭代,该事件流将EventFlow与.NET的标准软件包对齐。在此处发布只会支持.NET标准,.NET Core和.NET版本6+。

    • 发行
    • 仍在发展
    • 并非所有项目都迁移

    阅读迁移指南,以查看打破变化的完整列表以及有关如何迁移的建议。

    文档

    版本1.x文档已将其拉到此存储库中,以使代码和文档更加关闭,并将文档更新以与任何代码更改相同的拉值更新。该文档的编译版本可在https://gete*ven**tflow.net/上获得。

    Nuget软件包状态

    • ?移植
    • 新添加到1.0
    • ?尚未移植到1.0
    • ?对于作为1.0的一部分删除的软件包(有关详细信息,请参见《迁移指南》)

    项目

    • ? EventFlow
    • EventFlow .aspnetcore
    • EventFlow .autofac
    • ? EventFlow 。依赖性
    • EventFlow .elasticsearch
    • EventFlow .EntityFramework
    • EventFlow .EventStores.EventStore
    • EventFlow .hangfire
    • EventFlow .mongodb
    • EventFlow .MSSQL
    • EventFlow .OWIN
    • EventFlow .postgresql
    • EventFlow .Redis
    • EventFlow .rabbitmq
    • EventFlow .sql
    • EventFlow .sqlite
    • EventFlow .TestHelpers

    分支

    • 开发-V1:开发分支,拉力请求应在此处完成
    • Release-V1:发行分支,合并提交是从开发-V1的该分支完成的,以创建发行版。通常每个提交代表发布
  • 0.x(遗产)

    当前稳定版本的EventFlow版本已有将近六年的EventFlow版本。 0.x版本通过额外的Nuget软件包具有.NET框架支持和对Microsoft扩展程序包的支持有限。

    在对社区感兴趣的同时,仍将完成功能和错误修复版本。

    分支

    • 开发-V0:开发分支,拉力请求应在此处完成
    • Release-V0:发行分支,合并提交是从开发-V0完成此分支以创建发行版的。通常每个提交代表发布

    文档

    版本0.x文档(尽管有点过时)在https://docs.ge*t*eventf*low.net/上进行。

与EventFlow直接相关的谈话

  • Rasmus实用事件采购使用EventFlow ,Goto Aarhus 2022

例子

  • 完成:显示了如何将EventFlow与内存事件存储一起使用的完整示例,并以相对较少的代码行读取模型
  • 运输:要获得一个更完整的示例,说明如何使用EventFlow ,请查看代码库中此处找到的运输示例。该示例基于埃里克·埃文斯(Eric Evans)的“域驱动设计 – 解决软件中心的复杂性”一书中的运输示例。它的过程中,但应提供有关如何在更大范围内使用EventFlow灵感。如果您有想法和/或评论,请创建拉动请求或问题

外部示例

不同社区成员创建的示例列表。请注意,其中许多示例将使用EventFlow 0.x。

创建一个拉动请求,以从这里链接您的检查。

  • Recetimes:显示了EventFlow的某些功能,这些功能在完整的示例中未介绍。它具有实体,一个用于实体的读取模型,在读取模型,规格和快照上删除。

    • Azure功能的Recetime:扩展上述示例,以支持HTTP访问通过Azure函数

    • Azure功能和事件网格的Recetime:进一步扩展了Azure函数示例以发布到事件网格,遵循RabbitMQ模式

  • .NET CORE:使用事件流的Web API运行.NET CORE 2.2。它使用完整示例中的预定义命令/实体/事件。有终点可以创建一个新的示例事件,获取数据模型并重播所有数据模型。

  • Elasticsearch/.NET Core:它配置了EventFlow ,Elasticsearch,EventStore和RabbitMQ。有关#384,请参见“ withrabbitmq”分支。

  • 车辆跟踪:以基于docker为基础的.NET CORE 2.2上的微服务,您可以使用Docker-Compose进行服务,该项目使用各种工具来提高服务。 Linux Docker基于.NET Core,RabbitMQ,带有SQL Server的EntityFramework以及使用cqrs-es架构之后的EventFlow ,所有微服务都可以通过使用Ocelot的Apigateway访问

  • RESTAIRLINE:基于EventFlow的HyperMedia API项目,具有CQRS-ES的经典DDD。它针对ASP.NET Core 2.2,可以部署到Docker和K8。

  • 完整示例: .NET Core 2.2上的控制台应用程序。您可以使用Docker-Compose文件来提高服务。 Docker-Compose文件包括EventStore,RabbitMQ,MongoDB和PostgreSQL。它包括以下EventFlow概念:

    • 聚合
    • 命令巴士和命令
    • 同步订户
    • 活动商店(GES)
    • 内存读取模型。
    • 快照(mongodb)
    • 萨加斯
    • 事件出版(内存,兔子)
    • 元数据
    • 命令总线装饰器,自定义值对象,自定义执行结果,…

概述

这是EventFlow概念的列表。使用链接导航到文档。

  • 聚合:域对象,以保证每个聚合中进行更改的一致性
  • 命令总线和命令:所有命令/操作执行的入口点。
  • 事件存储:聚合的事件流的存储。当前有对这些存储类型的支持。

    • 内存 – 仅用于测试
    • 文件 – 仅用于测试
    • Microsoft SQL Server
    • 实体框架核心
    • sqlite
    • Postgresql
    • EventStore-主页
  • 订户:对特定领域事件行动的听众。如果需要在域事件进行后需要触发特定的操作,则有用。
  • 读取模型:针对快速阅读的聚合事件的典型化表示。当前有对这些读取模型存储类型的支持。对于SQL存储类型,查询是通过引用的列和表名称自动生成的。

    • Elasticsearch
    • 内存 – 仅用于测试
    • Microsoft SQL Server
    • 实体框架核心
    • sqlite
    • Postgresql
  • 快照:可以每次都可以创建一个快照,而不是每次读取整个事件流,而是包含聚集状态的每隔一段时间。 EventFlow支持升级现有快照,这对于长寿命骨料很有用。 EventFlow中的快照是选择加入的, EventFlow具有支持

    • 内存 – 仅用于测试
    • Microsoft SQL Server
    • 实体框架核心
    • sqlite
    • Postgresql
  • 传说:也称为过程管理者,坐标和路由有限上下文和聚合之间的消息
  • 查询:代表查询的值的值,而无需指定其执行的执行方式,请询问查询处理程序
  • 作业:以后执行计划的任务,例如发布命令。 EventFlow为这些工作调度程序提供支持

    • Hangfire-主页
  • 事件升级:随着致力于活动商店的事件从未更改, EventFlow使用事件升级器的概念来贬低事件并在汇总负载期间将其替换为新事件。
  • 事件发布:有时您希望其他应用程序或服务在域上消费并采取行动。对于此EventFlow支持事件发布。

    • 兔子
  • 元数据:每个聚合事件的其他信息,例如要发射的事件背后的用户IP。 EventFlow船与几个准备使用的提供商。
  • 值对象:包含用于验证和保存域数据的类的数据,例如用户名或电子邮件。

完整的示例

这是一个完整的示例,讲述了如何使用默认内存事件商店以及内存读取模型。

该示例包括以下类,每个类别如下所示

  • estepleaggregate:骨料根
  • 示例ID:代表聚集根的身份的值对象
  • 示例event:聚集根发射的事件
  • extplecommand:值对象定义可以发布到聚集根的命令
  • extplecommandhandler:命令处理程序使用其IOC容器解决哪个EventFlow并定义如何将命令特定应用于聚合根
  • ExipplereadModel:内存读取模型,可轻松访问当前状态

注意:此示例是EventFlow测试套件的一部分,因此请查看代码并尝试一下。

EventFlow with all of our classes. Instead of adding events,
// commands, etc. explicitly, we could have used the the simpler
// AddDefaults(Assembly) instead.
var serviceCollection = new ServiceCollection()
.AddLogging()
.Add EventFlow (o => o
.AddEvents(typeof(ExampleEvent))
.AddCommands(typeof(ExampleCommand))
.AddCommandHandlers(typeof(ExampleCommandHandler))
.UseInMemoryReadStoreFor<ExampleReadModel>());

using (var serviceProvider = serviceCollection.BuildServiceProvider())
{
// Create a new identity for our aggregate root
var exampleId = ExampleId.New;

// Resolve the command bus and use it to publish a command
var commandBus = serviceProvider.GetRequiredService<ICommandBus>();
await commandBus.PublishAsync(
new ExampleCommand(exampleId, 42), CancellationToken.None);

// Resolve the query handler and use the built-in query for fetching
// read models by identity to get our read model representing the
// state of our aggregate root
var queryProcessor = serviceProvider.GetRequiredService<IQueryProcessor>();
var exampleReadModel = await queryProcessor.ProcessAsync(
new ReadModelByIdQuery<ExampleReadModel>(exampleId), CancellationToken.None);

// Verify that the read model has the expected magic number
exampleReadModel.MagicNumber.Should().Be(42);
}
}\”>

 [ Test ]
public async Task Example ( )
{
  // We wire up EventFlow with all of our classes. Instead of adding events,
  // commands, etc. explicitly, we could have used the the simpler
  // AddDefaults(Assembly) instead.
  var serviceCollection = new ServiceCollection ( )
    . AddLogging ( )
    . Add EventFlow ( o => o
      . AddEvents ( typeof ( ExampleEvent ) )
      . AddCommands ( typeof ( ExampleCommand ) )
      . AddCommandHandlers ( typeof ( ExampleCommandHandler ) )
      . UseInMemoryReadStoreFor < ExampleReadModel > ( ) ) ;

  using ( var serviceProvider = serviceCollection . BuildServiceProvider ( ) )
  {
    // Create a new identity for our aggregate root
    var exampleId = ExampleId . New ;

    // Resolve the command bus and use it to publish a command
    var commandBus = serviceProvider . GetRequiredService < ICommandBus > ( ) ;
    await commandBus . PublishAsync (
      new ExampleCommand ( exampleId , 42 ) , CancellationToken . None ) ;

    // Resolve the query handler and use the built-in query for fetching
    // read models by identity to get our read model representing the
    // state of our aggregate root
    var queryProcessor = serviceProvider . GetRequiredService < IQueryProcessor > ( ) ;
    var exampleReadModel = await queryProcessor . ProcessAsync (
      new ReadModelByIdQuery < ExampleReadModel > ( exampleId ) , CancellationToken . None ) ;

    // Verify that the read model has the expected magic number
    exampleReadModel . MagicNumber . Should ( ) . Be ( 42 ) ;
  }
} 

EventFlow
// provides several different methods for doing this, e.g. state objects,
// the Apply method is merely the simplest
public void Apply(ExampleEvent aggregateEvent)
{
_magicNumber = aggregateEvent.MagicNumber;
}
}\”>

 // The aggregate root
public class ExampleAggregate : AggregateRoot < ExampleAggregate , ExampleId > ,
  IEmit < ExampleEvent >
{
  private int ? _magicNumber ;

  public ExampleAggregate ( ExampleId id ) : base ( id ) { }

  // Method invoked by our command
  public void SetMagicNumber ( int magicNumber )
  {
    if ( _magicNumber . HasValue )
      throw DomainError . With ( \"Magic number already set\" ) ;

    Emit ( new ExampleEvent ( magicNumber ) ) ;
  }

  // We apply the event as part of the event sourcing system. EventFlow
  // provides several different methods for doing this, e.g. state objects,
  // the Apply method is merely the simplest
  public void Apply ( ExampleEvent aggregateEvent )
  {
    _magicNumber = aggregateEvent . MagicNumber ;
  }
} 
 // Represents the aggregate identity (ID)
public class ExampleId : Identity < ExampleId >
{
  public ExampleId ( string value ) : base ( value ) { }
} 
 // A basic event containing some information
public class ExampleEvent : AggregateEvent < ExampleAggregate , ExampleId >
{
  public ExampleEvent ( int magicNumber )
  {
      MagicNumber = magicNumber ;
  }

  public int MagicNumber { get ; }
} 
 // Command for update magic number
public class ExampleCommand : Command < ExampleAggregate , ExampleId >
{
  public ExampleCommand (
    ExampleId aggregateId ,
    int magicNumber )
    : base ( aggregateId )
  {
    MagicNumber = magicNumber ;
  }

  public int MagicNumber { get ; }
} 
 // Command handler for our command
public class ExampleCommandHandler
  : CommandHandler < ExampleAggregate , ExampleId , ExampleCommand >
{
  public override Task ExecuteAsync (
    ExampleAggregate aggregate ,
    ExampleCommand command ,
    CancellationToken cancellationToken )
  {
    aggregate . SetMagicNumber ( command . MagicNumber ) ;
    return Task . CompletedTask ; ;
  }
} 
 // Read model for our aggregate
public class ExampleReadModel : IReadModel ,
  IAmReadModelFor < ExampleAggregate , ExampleId , ExampleEvent >
{
  public int MagicNumber { get ; private set ; }

  public Task ApplyAsync (
    IReadModelContext context ,
    IDomainEvent < ExampleAggregate , ExampleId , ExampleEvent > domainEvent ,
    CancellationToken _cancellationToken
  {
    MagicNumber = domainEvent . AggregateEvent . MagicNumber ;
    return Task . CompletedTask ;
  }
} 

EventFlow的状态

EventFlow仍在开发中,尤其是有关读取模型如何重新填充的部分。

EventFlow目前用于生产环境中,并且性能很好,但是在关键API稳定之前需要成熟。

EventFlow被极大地有用,但是可以通过注册不同的接口实现来为EventFlow的每个部分创建新的实现。

与EventFlow和DDD有关的有用文章

EventFlow中的许多技术设计决策都是基于文章。本节列出了其中一些。如果您与相关文章有链接,请通过与链接创建问题来分享。

  • 域驱动的设计

    • 埃里克·埃文斯(Eric Evans)由域驱动的设计参考
    • DDD解码 – 有限上下文解释了
    • 通过事件暴风雨和DDD进行微服务的“赛事优先”
  • 一般CQRS+ES

    • Microsoft出版的Microsoft的CQRS旅程
    • 深入了解Mike Mogosanu的CQRS
    • CQR,基于任务的UI,事件采购AGH!格雷格·杨(Greg Young)
    • 破坏吉米·鲍加德(Jimmy Bogard)的一些CQRS神话
    • 加布里埃尔·申克(Gabriel Schenker)应用的CQR
    • DDD解码 – 解释的实体和价值对象
  • 最终的一致性

    • 如何确保Mike Mogosanu最终一致的DDD/CQRS应用程序中的势力
    • DDD解码 – 不要担心最终的一致性
  • 为什么不在DDD中实现“工作单位”

    • 工作单位是Mike Mogosanu的新Singleton
    • Mike Mogosanu的工作和交易单位

集成测试

EventFlow具有多个测试,可以验证其使用与其正确集成的系统的能力。

  • Elasticsearch
  • 事件店
  • 兔子
  • Microsoft SQL Server
  • Postgresql

要设置本地测试环境,请在EventFlow的结帐目录中运行以下命令。

docker-compose pull
docker-compose up

另外,您可以跳过以集成类别标记的Nunit测试。

谢谢

  • 贡献者
  • Jetbrains:OSS许可证
  • Olholm:当前徽标
  • IconMonstr:第一个徽标
  • JC008:SQLite的Navicat Essentials许可证

执照

EventFlow最初是在我在eBay(2015年至2021年)和Schibsted(2021年及以前)工作的业余时间开发的。

EventFlow

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the \”Software\”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED \”AS IS\”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.\”>

The MIT License (MIT)

Copyright (c) 2015-2025 Rasmus Mikkelsen
https://github**.co*m/EventFlow/ EventFlow

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the \"Software\"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

下载源码

通过命令行克隆项目:

git clone https://github.com/eventflow/EventFlow.git

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 开发教程 EventFlow https://www.zuozi.net/31725.html

BruteShark
上一篇: BruteShark
abot
下一篇: abot
常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务