Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DbContextTransaction and Multi-thread: The connection is already in a transaction and cannot participate in another transaction

I got this error when I was trying to call same method with multiple threads: The connection is already in a transaction and cannot participate in another transaction. EntityClient does not support parallel transactions.

And I found that my issue somehow is similar to this: SqlException from Entity Framework - New transaction is not allowed because there are other threads running in the session

My scenario: I have a class that is instantiated by multiple theads, each thread - new instance:

public MarketLogic()
{ 
      var dbContext = new FinancialContext();
      AccountBalanceRepository = new AccountBalanceRepository(dbContext);
      CompositeTradeRepository = new CompositeTradeRepository(
         new OrderRepository(dbContext)
         , new PositionRepository(dbContext)
         , new TradeRepository(dbContext));

      CompositeRepository = new CompositeRepository(
         new LookupValueRepository(dbContext)
         , new SecurityRepository(dbContext)
         , new TransactionRepository(dbContext)
         , new FinancialMarketRepository(dbContext)
         , new FinancialMarketSessionRepository(dbContext)
         );
}

In MarketLogic class, SavePosition() is used to save information into database using Entity Framework DbContext. (SaveChanges()) method.

private void SavePosition()
{
   using (DbContextTransaction transaction = CompositeTradeRepository.OrderRepository.DbContext.Database.BeginTransaction())
   {
            try
            {
                   // business logic code, **this take some times to complete**.
                   position = EntityExistsSpecification.Not().IsSatisfiedBy(position)
                              ? CompositeTradeRepository.PositionRepository.Add(position)
                              : CompositeTradeRepository.PositionRepository.Update(position);
                   transaction.Commit();
            }
            catch (Exception exception)
            {
                // some code
                transaction.Rollback();
            }
    }
}

public Position Add(Position position)
{
   // some code
   // context is a instance of FinancialContext, this class is generated by Entity Framework 6
   context.SaveChanges();
}

In my scenario, the issue happened when there are 2 threads and more try to call new MarketLogic().SavePosition().

I can see that while the first transaction is not completed yet, the second thread come in and start a new transaction.

But I dont understand why 2 threads are in different DbContext object BUT the error still happens

So what is wrong? Or did I miss something?

like image 367
Vu Nguyen Avatar asked Feb 02 '26 15:02

Vu Nguyen


1 Answers

My fault, I left the repositories as static, so all thread shared same repositories, which means they shared same DbContext, which caused the issue when the EF didn't finished permitting changes yet and other call to SaveChanges() is made. So EF throwed exception.

like image 173
Vu Nguyen Avatar answered Feb 05 '26 05:02

Vu Nguyen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!