Vu Nguyen
Vu Nguyen

Reputation: 3665

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?

Upvotes: 3

Views: 7794

Answers (1)

Vu Nguyen
Vu Nguyen

Reputation: 3665

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.

Upvotes: 4

Related Questions