DbContextTransaction和多线程:连接已经在事务中,不能参与另一个事务

时间:2014-03-20 10:04:56

标签: c# multithreading entity-framework transactions thread-safety

当我尝试使用多个线程调用相同的方法时出现此错误:连接已在事务中,无法参与另一个事务。 EntityClient不支持并行事务。

我发现我的问题与此类似:SqlException from Entity Framework - New transaction is not allowed because there are other threads running in the session

我的方案: 我有一个由多个theads实例化的类,每个线程 - 新实例:

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)
         );
}

MarketLogic 类中, SavePosition()用于使用Entity Framework DbContext将信息保存到数据库中。 ( SaveChanges())方法。

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();
}

在我的方案中,问题发生在有2个线程且更多尝试调用 new MarketLogic()。SavePosition()

我可以看到,当第一个交易尚未完成时,第二个线程进入并开始一个新交易。

但我不明白为什么2个线程在不同的DbContext对象中但仍然发生错误

那有什么不对?或者我错过了什么?

1 个答案:

答案 0 :(得分:2)

我的错,我将存储库保留为静态,因此所有线程都共享相同的存储库,这意味着它们共享相同的DbContext,这在EF尚未完成允许更改时导致问题并且进行了对SaveChanges()的其他调用。因此EF抛出异常。