MassTransit: Not able to update Entity framework Core relationship from Saga Event

I am unable to update the entity relationship in my instance event. I am able to create One-to-One relational row for an entry however while I come back to the state again it is not detecting the row is already exist

Here is my State Machine

public class IssueRequestStateMachine: MassTransitStateMachine<IssueRequest>
{
	public CustomerIssueStateMachine()
	{
		InstanceState(x => x.CurrentState);

		State(() => IssueTypeAndDetails);
		State(() => IssueLocation);
		State(() => IssueDetails);
		State(() => RequestSubmit);
		State(() => RequestAcknowledgement);


		Event(() => NewIssueTypeAndDetailsSubmitted,
			cfg => cfg.CorrelateById(instance => instance.UserId, 
				dtocontext => dtocontext.Message.UserId)
			.SelectId(dtocontext =>
			{
				return NewId.NextGuid();
			}));

		Event(() => IssueTypeAcceptedAtIssueLocation,
			cfg => cfg.CorrelateById(dtocontext => dtocontext.Message.CorrelationId));

		Event(() => IssueLocationAcceptedAtIssueDetails,
			cfg => cfg.CorrelateById(dtocontext => dtocontext.Message.CorrelationId));

		Event(() => RequestSubmittedToBackend,
			cfg => cfg.CorrelateById(dtocontext => dtocontext.Message.CorrelationId));

		Event(() => BackendAcknowledged,
			cfg => cfg.CorrelateById(dtocontext => dtocontext.Message.CorrelationId));

		Initially(
			When(NewIssueTypeAndDetailsSubmitted)
			.Then(context =>
			{
				context.Instance.FirstName = context.Data.FirstName;
				context.Instance.LastName = context.Data.LastName;
			})
			.TransitionTo(IssueTypeAndDetails));

		During(IssueTypeAndDetails,
			When(IssueTypeAcceptedAtIssueLocation)
			.Then(context => {
				//This is creating new Issue Location every time when I come back to the state, this expected to be updated 
				//If I come back to this state
				context.Instance.IssueLocation = new IssueLocation(context.Instance.CorrelationId)
				{
					State = context.Data.State,
					PostCode = context.Data.PostCode
				};

			}).TransitionTo(IssueLocation));

			
		During(IssueLocation,
			When(IssueLocationAcceptedAtIssueDetails)
			.Then(context => {
				context.Instance.IssueDetailsText = context.Data.IssueDetailsText;
			}).TransitionTo(IssueDetails));

			
		During(IssueDetails,
			When(IssueDetailsAcceptedAtRequestorContact)
			.Then(context =>
			{
				context.Instance.Email = context.Data.Email;
				
			}).TransitionTo(RequestSubmit));


		During(RequestSubmit,
			When(BackendAcknowledged)
			.Then(context =>
			{
				context.Instance.AcknowledgementDate = context.Data.AcknowledgementDate;
				
			}).TransitionTo(RequestAcknowledgement));

	}


	public State IssueTypeAndDetails { get; set; }
	public State IssueLocation { get; set; }
	public State IssueDetails { get; set; }
	public State RequestSubmit { get; set; }
	public State RequestAcknowledgement { get; set; }


	public Event<IssueTypeAndDetailsDTO> NewIssueTypeAndDetailsSubmitted { get; set; }
	public Event<IssueLocationDTO> IssueTypeAcceptedAtIssueLocation { get; set; }
	public Event<IssueDetailsDTO> IssueLocationAcceptedAtIssueDetails { get; set; }
	public Event<RequestSubmitDTO> RequestSubmittedToBackend { get; set; }
	public Event<RequestAcknowledgementDTO> BackendAcknowledged { get; set; }
	public Event Back { get; set; }
	public Event Cancel { get; set; }

}

Saga Instance

public class IssueRequest : SagaStateMachineInstance
{
	public IssueRequest(Guid correlationId):base(correlationId)
	{
		CorrelationId = correlationId;
	}

	public static IssueRequest Instance()
	{
		return new IssueRequest();
	}

	public IssueRequest():base(NewId.NextGuid())
	{

	}

	[Required]
	public string CurrentState { get; set; }

	[Required]
	public string FirstName { get; set; }

	[Required]
	public string LastName { get; set; }
	
	public IssueLocation IssueLocation { get; set; }

	public string IssueDetailsText { get; set; }

	public string Email { get; set; }

	public string ApplicationNumber { get; set; }
	
	public DateTime ApplicationDate { get; set; }

	public DateTime AcknowledgementDate { get; set; }
}

public class IssueLocation
{
	public IssueLocation()
	{
	}

	public IssueLocation(Guid correlationId) : base(correlationId)
	{
	}
	public Guid CorrelationId { get; set; }
	public string PostCode { get; set; }
	public string State { get; set; }
}

Saga Instance Mapping

public class IssueRequestMapping : IEntityTypeConfiguration<IssueRequest>
{
	public IssueRequestMapping()
	{
	}

	public void Configure(EntityTypeBuilder<IssueRequest> entityTypeBuilder)
	{
		entityTypeBuilder.Property(x => x.CorrelationId);
		entityTypeBuilder.Property(x => x.CurrentState).HasMaxLength(250).IsRequired();

		entityTypeBuilder.HasOne(a => a.IssueLocation).WithOne().HasForeignKey<IssueLocation>(a => a.CorrelationId);
	}
}

Db Context

public class IssueRequestDbContext : SagaDbContext<IssueRequest, IssueRequestMapping>
{
	public IssueRequestDbContext(DbContextOptions options) : base(options)
	{
	}

	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		modelBuilder.Ignore<ValidationResult>();
		
		modelBuilder.Entity<IssueRequest>().ToTable("IssueRequest");

		modelBuilder.Entity<IssueLocation>().ToTable("IssueLocation").HasKey(e => e.CorrelationId);

		base.OnModelCreating(modelBuilder);
	}

	public DbSet<IssueRequest> IssueRequest { get; set; }
}

Above code I need to update IssueLocation instead of adding new record(at IssueTypeAcceptedAtIssueLocation event). First time it is working but when I come back to the same state again that’s where it is trying to create new record. Since the record already existing in table it is throwing an error. Is there a right method to do it or is it kind of an issue out side of State Machine

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 20 (10 by maintainers)

Most upvoted comments

For now, I extended sagaRepo ctor with : Func<DbSet<TSaga>, IQueryable<TSaga>>

to configure DbSet when repo is called for SagaState, works pretty well.

Can you elborate this part of code ? I am using .net Core and Saga state machinbe dont know how to inject DB Context to it.