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

3
我在尝试使用多个线程调用同一个方法时,遇到了以下错误:连接已经处于事务中,无法参与另一个事务。EntityClient不支持并行事务。

我发现我的问题与此类似:Entity Framework的SqlException - 新事务不允许,因为会话中有其他线程正在运行

我的场景: 我有一个被多个线程实例化的类,每个线程-新实例:

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对象中,但错误仍然发生。 那么问题出在哪里?或者我错过了什么?

禁用多线程。错误还在吗? - usr
当然,如果只有一个线程,问题就消失了。但我的目的是让多个线程能够将信息保存到数据库,并且它们不应该知道彼此的存在。 - Vu Nguyen
1个回答

4

抱歉,我的错误在于将存储库设置为静态的,这意味着所有线程共享同一个存储库,也就是共享同一个DbContext,当EF尚未完成对更改的操作时,其他调用SaveChanges()的操作引起了问题。因此,EF抛出了异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接