C# 如何使用Akka.net和Akka.Persistence应用CQRS的事件总线

C# 如何使用Akka.net和Akka.Persistence应用CQRS的事件总线,c#,cqrs,akka.net,akka.net-persistence,C#,Cqrs,Akka.net,Akka.net Persistence,我对如何在Akka.net上应用CQR和事件资源感兴趣。我已经注意到哪个交付了ES部件 据我所知,命令处理程序和AggergateRoot可以由单个类中的ReceivePersistentActor表示。我有一个基类(这里不完整) 然而,在AggregateRoot域对象参与者中了解eventbus的实现对我来说似乎很奇怪。我可以把责任交给一个actor子级,或者注入类似IAbstractEventBus接口的东西,用于切换实现,但我认为在持久化后发布事件并通知所有订阅者不应该是Aggregat

我对如何在Akka.net上应用CQR和事件资源感兴趣。我已经注意到哪个交付了ES部件

据我所知,命令处理程序和AggergateRoot可以由单个类中的ReceivePersistentActor表示。我有一个基类(这里不完整)

然而,在AggregateRoot域对象参与者中了解eventbus的实现对我来说似乎很奇怪。我可以把责任交给一个actor子级,或者注入类似IAbstractEventBus接口的东西,用于切换实现,但我认为在持久化后发布事件并通知所有订阅者不应该是AggregateRoot的责任,对吗!? 但演员的角色似乎与演员有关

使用Akka.net和Akka.Persistence的典型方法是什么?有什么设计思路可以把它分开吗

我无意中发现了Akka.net的IEventAdapter接口,但我不确定这是否会让我走上正确的道路(或黑暗面)


在理想主义世界中,命令处理程序可以负责跟踪事件,以推送到事件总线,并将它们持久化到某种形式的存储,一旦命令完全处理完毕,不会出现任何问题-这确保在聚合方法完成引发它应该引发的所有事件之前不会过早推送事件

在Akka.net中,您可以在将命令传递给聚合时将Tell更改为Ask(假设为了纯度起见,您将处理程序与聚合分开),并让聚合将它想要引发和持久化的事件返回给处理程序,这样处理程序就可以发送和持久化它们(可能是间接地自己…可能是通过U.O.W.上的某种形式。)…但是,这意味着在聚合完成之前,无法处理命令处理程序配置为处理的其他命令…即使其他聚合可能由一个处理程序提供服务-毕竟,Ask锁…Tell不会

在其他一些系统中,持久层本身可以充当事件总线。Greg Young的EventStore就是其中之一……您可以完全消除应用程序中的顾虑)

这是理想主义理论与现实世界实现和框架限制的挑战

在理想主义世界中,聚合根本身并不关心存储它引发的事件。。。它的目的(有人会说)是从一个提供的事件集合中生成自身,引发事件,并让其他组件管理这些事件的广播、持久性和查询(用于生成)。我知道Akka.net为它的参与者提供了一个很好的DB访问/持久层。。。这很好。。。但确实偏离了纯固态CQRS实现。因此,您可能会开始在您的实现中弄浑,这就是您所处的位置

这远非理想,但却是一个选择

    protected virtual void Execute<TCommand>(Action<TCommand> action, TCommand command)
    {
        UnitOfWork.Add(this);
        try
        {
            action(command);

            UnitOfWork.Commit();

            Sender.Tell(true, Self);
        }
        catch(Exception exception)
        {
            Logger.LogError("Executing an Akka.net request failed.", exception: exception);
            Sender.Tell(false, Self);
            throw;
        }
    }
protectedvirtualvoid执行(操作、TCommand命令)
{
添加(此);
尝试
{
行动(指挥);
UnitOfWork.Commit();
告诉(真实的,自我);
}
捕获(异常)
{
Logger.LogError(“执行Akka.net请求失败”,异常:异常);
发送者。告诉(虚假,自我);
投掷;
}
}
然后可以通过

    Receive<SayHelloWorldCommand>(command => Execute(SayHello, command));
Receive(command=>Execute(SayHello,command));

这取自cqrs.net,它使用聚合中的工作单元(U.O.W.),而不是将其传递回处理程序。这是他们所做的一项综合性工作,至少要将上述问题直接排除在总体之外,并保持某种形式的可靠实施。

@Beachwalker我在网站上使用CQRS方法实施。我不知道这对你有没有帮助?但希望你能找到一些有用的东西。我将继续为它添加更多的功能和特性

public class SomeEventAdapter : IEventAdapter
{
    public object ToJournal(object evt)
    {
        return evt; // should I add the event emitter here?
        // but is this already stored now? hmmm
    }
}
    protected virtual void Execute<TCommand>(Action<TCommand> action, TCommand command)
    {
        UnitOfWork.Add(this);
        try
        {
            action(command);

            UnitOfWork.Commit();

            Sender.Tell(true, Self);
        }
        catch(Exception exception)
        {
            Logger.LogError("Executing an Akka.net request failed.", exception: exception);
            Sender.Tell(false, Self);
            throw;
        }
    }
    Receive<SayHelloWorldCommand>(command => Execute(SayHello, command));