Masstransit: Saga, Microsoft Dependency Injection and Entity Framework Core DbContext

Created on 14 Nov 2019  路  4Comments  路  Source: MassTransit/MassTransit

Hi, I'm trying to create a State Machine Saga for integration purposes. In a State I need to check in the database if the current register already exists to purge it from the integration. And I thinked to put that in the saga's depency injection the DbContext, but I had a problem, the DbContext is scoped and I saw it in the source code the Masstransit saga implementation is a singleton. I tried to find some examples about a similar implementation, but I could'nt find any one. Have someone to help me and others about it? Need I put that dependency on the saga's instance?

Most helpful comment

You should put the dependency in an activity, that you call from the state machine. I'm not sure if I have documented that yet 鈥撀爄t's on the list. The unit test shows how to do it:

Registration: https://github.com/MassTransit/MassTransit/blob/master/src/Containers/MassTransit.Containers.Tests/DependencyInjection_Tests/DependencyInjection_SagaStateMachine.cs#L36

State machine:
https://github.com/MassTransit/MassTransit/blob/master/src/Containers/MassTransit.Containers.Tests/Scenarios/StateMachines/TestStateMachineSaga.cs#L28

The dependency should be on the Activity, not the state machine or instance.

All 4 comments

You should put the dependency in an activity, that you call from the state machine. I'm not sure if I have documented that yet 鈥撀爄t's on the list. The unit test shows how to do it:

Registration: https://github.com/MassTransit/MassTransit/blob/master/src/Containers/MassTransit.Containers.Tests/DependencyInjection_Tests/DependencyInjection_SagaStateMachine.cs#L36

State machine:
https://github.com/MassTransit/MassTransit/blob/master/src/Containers/MassTransit.Containers.Tests/Scenarios/StateMachines/TestStateMachineSaga.cs#L28

The dependency should be on the Activity, not the state machine or instance.

It's awesome @phatboyg thank you so much. I'm making the changes in my code and let me get it work. I want to post here my implementation for someone in future. I saw today in MassTransit to find about Activities, and discovered that the community improved the documentation, it's get it so better.

Dependency Injection Registrations
``` config.Collection.AddScoped();
config.Collection.AddScoped();
config.Collection.AddScoped();
config.Collection.AddScoped();
config.Collection.RegisterInMemorySagaRepository();
config.AddSagaStateMachine();

Receive endpoint configuration
                cfg.ReceiveEndpoint(host, nespressoSulVerifyConfig.QueueName, e => {
                    e.BindMessageExchanges = false;

                    e.ConfigureSaga<VerificationLayoutSagaInstance>(provider);
                });
And I put the DbContext in the VerificationLayoutActivity.

public class VerificationLayoutSaga : MassTransitStateMachine<VerificationLayoutSagaInstance>
{
    #region States
    public State Verificate { get; private set; }
    public State Reject { get; private set; }
    public State Integrate { get; private set; }
    #endregion States

    #region Events
    public Event<IAquireFile> AcquireFile { get; private set; }
    #endregion Events

    #region Definition

    public VerificationLayoutSaga()
    {
        InstanceState(instance => instance.CurrentState);

        //Events
        Event(() => AcquireFile, x => x.CorrelateBy<Guid>(instance => instance.Lot, context => context.Message.Lot));

        SetCompletedWhenFinalized();

        //Executions
        Initially(
            When(AcquireFile)
                .Then(context => {
                    context.Instance.Customer = context.Data.Customer;
                    context.Instance.Name = context.Data.Name;
                    context.Instance.FullName = context.Data.FullName;
                    context.Instance.Date = context.Data.Date;
                    context.Instance.Lot = context.Data.Lot;
                })
                .Activity(acquire => acquire.OfInstanceType<AcquireFileActivity>())
                .TransitionTo(Verificate));

        WhenEnter(Verificate, 
            bind => bind
                .Activity(verify => verify.OfType<VerificationLayoutActivity>())
                .IfElse(
                    context => !context.Instance.Validated,
                    then => then.TransitionTo(Reject),
                    thenElse => thenElse.TransitionTo(Integrate)));

        WhenEnter(Reject,
            bind => bind
                .Activity(reject => reject.OfType<RejectFileActivity>())
                .Finalize());

        WhenEnter(Integrate,
            bind => bind
                .Activity(integrate => integrate.OfType<IntegrateFileActivity>())
                .Finalize());
    }
    #endregion Definition
}

```

Thanks for sharing your solution!

Was this page helpful?
0 / 5 - 0 ratings