使用EFCore持久性具有自动别名功能的多个状态机不起作用 [英] Multiple State machines with automatonymous using EFCore persistence not working

查看:70
本文介绍了使用EFCore持久性具有自动别名功能的多个状态机不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用具有自动别名功能的Masstransit和InMemoryRepository来实现传奇持久性.我们大约配置了3个状态机,并且工作正常.我们最近从InMemoryRepository更改为EFCore以实现持久性.这导致只有第一个配置的状态机才能正常运行.休息所有状态机甚至都没有进入Initially事件.需要帮助以了解实施是否正确.以下是代码详细信息:

We are using Masstransit with automatonymous and InMemoryRepository for saga persistence. We have around 3 state machines configured and working perfectly. We recently changed from InMemoryRepository to EFCore for persistence. This resulted in only the 1st configured state machine to work perfectly. Rest all statemachines are not even entering the Initially event. Need help to understand if the implementation is correct or not. Below are code details:

masstransit状态机设置

masstransit statemachine setup

 services.AddMassTransit(x =>
        {
            x.AddBus(provider => MassTransit.Bus.Factory.CreateUsingRabbitMq(cfg =>
            {
                cfg.Host(hostUri, hst =>
                {
                    hst.Username(appSettings.RabbitMQ.Username);
                    hst.Password(appSettings.RabbitMQ.Password);
                });

                cfg.ReceiveEndpoint("microservice-response", e =>
                {
                    AddConsumers(e, provider);
                    e.ConfigureSaga<ServiceRequest1RegisterState>(provider);
                    e.ConfigureSaga<ServiceRequest1UpdateState>(provider);
                    e.ConfigureSaga<ServiceRequest1ApproveState>(provider);
                });
            }));

            ////x.AddSagaStateMachine<ServiceRequest1RegisterStateMachine, ServiceRequest1RegisterState>()
            ////   .InMemoryRepository();
            ////x.AddSagaStateMachine<ServiceRequest1UpdateStateMachine, ServiceRequest1UpdateState>()
            ////   .InMemoryRepository();
            ////x.AddSagaStateMachine<ServiceRequest1ApproveStateMachine, ServiceRequest1ApproveState>()
            ////   .InMemoryRepository();

            x.AddSagaStateMachine<ServiceRequest1RegisterStateMachine, ServiceRequest1RegisterState>()
                .EntityFrameworkRepository(r =>
                {
                    r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion

                    r.AddDbContext<DbContext, ServiceRequest1RegisterStateDbContext>((provider, builder) =>
                    {
                        builder.UseSqlServer(configuration.GetConnectionString("StateDBConnection"), m =>
                        {
                            m.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name);
                            m.MigrationsHistoryTable($"__{nameof(ServiceRequest1RegisterStateDbContext)}");
                        });
                    });
                });

    x.AddSagaStateMachine<ServiceRequest1UpdateStateMachine, ServiceRequest1UpdateState>()
                .EntityFrameworkRepository(r =>
                {
                    r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion

                    r.AddDbContext<DbContext, ServiceRequest1UpdateStateDbContext>((provider, builder) =>
                    {
                        builder.UseSqlServer(configuration.GetConnectionString("StateDBConnection"), m =>
                        {
                            m.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name);
                            m.MigrationsHistoryTable($"__{nameof(ServiceRequest1UpdateStateDbContext)}");
                        });
                    });
                });

            x.AddSagaStateMachine<ServiceRequest1ApproveStateMachine, ServiceRequest1ApproveState>()
                .EntityFrameworkRepository(r =>
                {
                    r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion

                    r.AddDbContext<DbContext, ServiceRequest1ApproveStateDbContext>((provider, builder) =>
                    {
                        builder.UseSqlServer(configuration.GetConnectionString("StateDBConnection"), m =>
                        {
                            m.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name);
                            m.MigrationsHistoryTable($"__{nameof(ServiceRequest1ApproveStateDbContext)}");
                        });
                    });
                });
        });

        services.AddSingleton<IHostedService, MassTransitBusService>();

对于所有3个状态机,DBContext如下所示

DBContext looks like below for all 3 statemachines

 public class ServiceRequest1ApproveStateDbContext : SagaDbContext
{
    public ServiceRequest1ApproveStateDbContext(DbContextOptions<ServiceRequest1ApproveStateDbContext> options)
        : base(options)
    {
    }

    /// <summary>
    /// Gets the configurations.
    /// </summary>
    protected override IEnumerable<ISagaClassMap> Configurations
    {
        get { yield return new ServiceRequest1ApproveStateMap(); }
    }
}

下面的状态图

public class ServiceRequest1ApproveStateMap : SagaClassMap<ServiceRequest1ApproveState>
{
    protected override void Configure(EntityTypeBuilder<ServiceRequest1ApproveState> entity, ModelBuilder model)
    {
        entity.Property(x => x.CurrentState).HasMaxLength(64);
        entity.Property(x => x.Id);
        entity.Property(x => x.ServiceId);
        entity.Property(x => x.ReadyEventStatus);
    }
}

从上面的代码中,只有ServiceRequest1RegisterStateMachine可以正常工作,其余的状态机甚至都不会进入Initially.我可以确认所有迁移都是事先完成的,并且当仅存在1个存储库配置时,这些状态机都可以单独正常工作,即,如果仅ServiceRequest1ApproveStateMachine的repo config,则此状态机可以正常工作.但是,如果所有3个repo配置都存在,则只有第1个有效.我需要有关使用EFCore正确实现传奇持久性的指导.我是否应该尝试使用masstransit docs( https://masstransit-project.com/usage/sagas/efcore.html )

From the above code, only the ServiceRequest1RegisterStateMachine works perfectly, the rest statemachines dont even enter Initially. I can confirm that the migrations are all done beforehand and these statemachine are all working fine individually when only 1 repository configuration exists, ie, if only repo config for ServiceRequest1ApproveStateMachine, this state machine works fine. But if all 3 repo config exists, then only the 1st works. I need guidance on correctly implementing saga persistence using EFCore. Should I try implementing using single dbcontext as mentioned in masstransit docs(https://masstransit-project.com/usage/sagas/efcore.html)

推荐答案

以下是我为确保状态机按预期工作所做的更改.即使我们最初的状态机实现是基于sqlserver efcore持久性的文档,更改也是基于@Chris建议的注释进行的.

So below are the changes i did to ensure the statemachine works as expected. The changes were done based on @Chris suggestion in comments, even though our initial implementation of the statemachine was based on the docs on sqlserver efcore persistence.

services.AddDbContext<ServiceRequest1RegisterStateDbContext>(x =>
                     x.UseSqlServer(configuration.GetConnectionString("StateDBConnection")));
        services.AddDbContext<ServiceRequest1UpdateStateDbContext>(x =>
                       x.UseSqlServer(configuration.GetConnectionString("StateDBConnection")));
        services.AddDbContext<ServiceRequest1ApproveStateDbContext>(x =>
                        x.UseSqlServer(configuration.GetConnectionString("StateDBConnection")));

services.AddMassTransit(x =>
    {
        x.AddBus(provider => MassTransit.Bus.Factory.CreateUsingRabbitMq(cfg =>
        {
            cfg.Host(hostUri, hst =>
            {
                hst.Username(appSettings.RabbitMQ.Username);
                hst.Password(appSettings.RabbitMQ.Password);
            });

            cfg.ReceiveEndpoint("microservice-response", e =>
            {
                AddConsumers(e, provider);
                e.ConfigureSaga<ServiceRequest1RegisterState>(provider);
                e.ConfigureSaga<ServiceRequest1UpdateState>(provider);
                e.ConfigureSaga<ServiceRequest1ApproveState>(provider);
            });
        }));

        ////x.AddSagaStateMachine<ServiceRequest1RegisterStateMachine, ServiceRequest1RegisterState>()
        ////   .InMemoryRepository();
        ////x.AddSagaStateMachine<ServiceRequest1UpdateStateMachine, ServiceRequest1UpdateState>()
        ////   .InMemoryRepository();
        ////x.AddSagaStateMachine<ServiceRequest1ApproveStateMachine, ServiceRequest1ApproveState>()
        ////   .InMemoryRepository();

        x.AddSagaStateMachine<ServiceRequest1RegisterStateMachine, ServiceRequest1RegisterState>()
            .EntityFrameworkRepository(r =>
            {
                r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion

                r.ExistingDbContext<ServiceRequest1RegisterStateDbContext>();
            });

x.AddSagaStateMachine<ServiceRequest1UpdateStateMachine, ServiceRequest1UpdateState>()
            .EntityFrameworkRepository(r =>
            {
                r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion

                r.ExistingDbContext<ServiceRequest1UpdateStateDbContext>();
            });

        x.AddSagaStateMachine<ServiceRequest1ApproveStateMachine, ServiceRequest1ApproveState>()
            .EntityFrameworkRepository(r =>
            {
                r.ConcurrencyMode = ConcurrencyMode.Pessimistic; // or use Optimistic, which requires RowVersion

                r.ExistingDbContext<ServiceRequest1ApproveStateDbContext>();
            });
    });

    services.AddSingleton<IHostedService, MassTransitBusService>();

}

这篇关于使用EFCore持久性具有自动别名功能的多个状态机不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆