【问题标题】:DbContextTransaction and Multi-thread: The connection is already in a transaction and cannot participate in another transactionDbContextTransaction 和多线程:连接已经在一个事务中,不能参与另一个事务
【发布时间】:2014-03-20 10:04:55
【问题描述】:

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

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

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

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 对象中但错误仍然发生

那么有什么问题吗?还是我错过了什么?

【问题讨论】:

  • 禁用多线程。错误还在吗?
  • 当然,如果只有一个线程。问题消失了。但是我想要的是多线程可以将信息保存到数据库中,并且它们应该不知道彼此。

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


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2019-01-02
    • 2011-05-28
    • 2012-09-30
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    相关资源
    最近更新 更多