Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

178
Views
Enlist Rebus in a TransactionScope combined with Entity Framework Core 3.0 without 2-phase commit

I am using Entity Framework Core with PostgreSQL. I want to override SaveChanges in my DbContext to both commit the EF changes and send a message with Rebus within the same database transaction. The plan is to also use PostgreSQL for transport etc, but I am having trouble merely enlisting Rebus in a transaction scope using the code below.

       public override int SaveChanges()
        {
            using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                tx.EnlistRebus();
                var result = base.SaveChanges();
                //TODO: _bus.Send("something happened");
                tx.Complete();
                return result;
            }
        }

Running the above results in PostgresException: 55000: prepared transactions are disabled, which is true, since my PostgreSQL configuration has not enabled it. My question is why Rebus needs to cause a 2-phase commit here. Maybe I'm missing something, though I would hope a 2PC is not needed, given both Entity Framework and Rebus will use the same relational database instance.

The call to EnlistRebus is in the Rebus.TransactionScopes package and does not know what transport implementation is in use and might do the safe thing.

Is there another way to do both the database operation and Rebus send transactionally without 2-phase commit? I can of course use a separate table to store my pending message from SaveChanges and have a separate worker pull from that table and send the message using Rebus. I suspect this approach is the most solid and straightforward.

I am using Rebus 6.3.0, Rebus.PostgreAql 7.1.0, Rebus.TransactionScopes 6.0.0, Npgsql 4.1.3.1, Npgsql.EntityframeworkCore.PostgreSQL 3.1.4 and EF Core 3.1.4.

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Rebus.PostgreSQL will actually enlist in the ambient transaction by itself without Rebus.TransactionScopes.

Looking at the Rebus.PostgreSQL repo, I saw there was a PR that seems to solve my issue. Quote from the PR at https://github.com/rebus-org/Rebus.PostgreSql/pull/14:

I first tried getting https://github.com/rebus-org/Rebus.TransactionScopes to work, but that does not seem to do anything using the postgresql transport.

To verify that it does indeed do the message publishing in the ambient transaction, I did the following modification:

    public override int SaveChanges()
    {
        using (var tx = new TransactionScope(TransactionScopeOption.Required,
            new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }, 
            TransactionScopeAsyncFlowOption.Enabled))
        {

            var result = base.SaveChanges();
            _bus.Send(new MyMessage { CurrentDateTime = DateTime.Now}).Wait();
            if (ShouldCrash)
            {
                throw new ArgumentException();
            }
            tx.Complete();
            return result;
        }
    }

If ShouldCrash is set to true, no message is published and no changes are made to the entities. If ShouldCrash is set to false both message publishing and entity change are performed.

I think this works because of the following from the Npgsql docs:

Note that if you open and close connections to the same database inside an ambient transaction, without ever having two connections open at the same time, Npgsql will internally reuse the same connection, avoiding the escalation to a full-blown distributed transaction.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!